为什么这在 Microsoft SQL Server Management Studio 下有效,但在 R 下无效?
Why does this work under Microsoft SQL Server Management Studio but not under R?
我收到此 SQL 声明:
use MYDATABASE;
if object_id('tempdb..#mapDT') is not null drop table #mapDT;
create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
insert into #mapDT SELECT 'varchar','type text' UNION ALL SELECT 'datetime','type datetime'UNION ALL SELECT 'tinyint','int64.Type' UNION ALL SELECT 'int','int64.Type' UNION ALL SELECT 'float','type number';
SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + 'MyString3' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
并且它 运行 在 MS SSMS 下运行良好。结果的相关部分是:
MyString1COLUMN01MyString2type textMyString3
MyString1COLUMN02MyString2type datetimeMyString3
MyString1COLUMN03MyString2type textMyString3
MyString1COLUMN04MyString2type textMyString3
MyString1COLUMN05MyString2int64.TypeMyString3
MyString1COLUMN06MyString2type datetimeMyString3
MyString1COLUMN07MyString2type datetimeMyString3
... ... ...
当我 运行 它在 R
下时,我必须省略 use MYDATABASE;
并确保我连接到正确的数据库,就是这种情况。但是 SQL 语句是有问题的。的输出:
> library(odbc)
> conn <- dbConnect(odbc(), Driver = "SQL Server", Server = "MYSERVER\MYINSTANCE", Database = "MYDATABASE", Trusted_Connection = "True")
> dbGetQuery(conn, "
+ if object_id('tempdb..#mapDT') is not null drop table #mapDT; create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
+ insert into #mapDT SELECT 'varchar', 'type text' UNION ALL SELECT 'datetime', 'type datetime' UNION ALL SELECT 'tinyint', 'int64.Type' UNION ALL SELECT 'int', 'int64.Type' UNION ALL SELECT 'float', 'type number';
+ SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + 'MyString3' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
+ ")
是data frame with 0 columns and 0 rows
。
是不是使用了"temporal tables"(即#mapDT)导致空数据框?如果是这样,有没有办法让 R
and/or Python
到 understand/use 他们?
正如 Gord Thompson 所知,代码应包含 SET NOCOUNT ON;
。因此,
> library(odbc)
> conn <- dbConnect(odbc(), Driver = "SQL Server", Server = "MYSERVER\MYINSTANCE", Database = "MYDATABASE", Trusted_Connection = "True")
> dbGetQuery(conn, "
+ SET NOCOUNT ON; if object_id('tempdb..#mapDT') is not null drop table #mapDT; create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
+ insert into #mapDT SELECT 'varchar', 'type text' UNION ALL SELECT 'datetime', 'type datetime' UNION ALL SELECT 'tinyint', 'int64.Type' UNION ALL SELECT 'int', 'int64.Type' UNION ALL SELECT 'float', 'type number';
+ SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + '},' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
+ ")
在我的例子中不需要行号,所以我也使用了 formals(print.data.frame)$row.names <- FALSE
:
> library(odbc)
> conn <- dbConnect(odbc(), Driver = "SQL Server", Server = "MYSERVER\MYINSTANCE", Database = "MYDATABASE", Trusted_Connection = "True")
> formals(print.data.frame)$row.names <- FALSE
> dbGetQuery(conn, "
+ SET NOCOUNT ON; if object_id('tempdb..#mapDT') is not null drop table #mapDT; create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
+ insert into #mapDT SELECT 'varchar', 'type text' UNION ALL SELECT 'datetime', 'type datetime' UNION ALL SELECT 'tinyint', 'int64.Type' UNION ALL SELECT 'int', 'int64.Type' UNION ALL SELECT 'float', 'type number';
+ SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + 'MyString3' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
+ ")
> formals(print.data.frame)$row.names <- TRUE
尽管如此,请考虑避免任何触发 NOCOUNT
的 DML 语句,因为您的临时 table 是不必要的。只需 运行 子查询 JOIN
即可获得更简单、可读、可维护的查询。下面 CONCAT
将 varchar 字段和名称计算列上的 +
替换为别名,OUTPUT
:
SELECT COLUMN_NAME, DATA_TYPE,
CONCAT('MyString1', COLUMN_NAME,
'MyString2', m.MyNewDataType,
'MyString3') AS OUTPUT
FROM INFORMATION_SCHEMA.COLUMNS C
INNER JOIN
( SELECT 'varchar' AS SqlDatatype, 'type text' AS MyNewDataType
UNION ALL SELECT 'datetime', 'type datetime'
UNION ALL SELECT 'tinyint', 'int64.Type'
UNION ALL SELECT 'int', 'int64.Type'
UNION ALL SELECT 'float', 'type number'
) m
ON m.SqlDatatype = C.DATA_TYPE
WHERE TABLE_NAME = 'MYTABLE';
我收到此 SQL 声明:
use MYDATABASE;
if object_id('tempdb..#mapDT') is not null drop table #mapDT;
create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
insert into #mapDT SELECT 'varchar','type text' UNION ALL SELECT 'datetime','type datetime'UNION ALL SELECT 'tinyint','int64.Type' UNION ALL SELECT 'int','int64.Type' UNION ALL SELECT 'float','type number';
SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + 'MyString3' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
并且它 运行 在 MS SSMS 下运行良好。结果的相关部分是:
MyString1COLUMN01MyString2type textMyString3
MyString1COLUMN02MyString2type datetimeMyString3
MyString1COLUMN03MyString2type textMyString3
MyString1COLUMN04MyString2type textMyString3
MyString1COLUMN05MyString2int64.TypeMyString3
MyString1COLUMN06MyString2type datetimeMyString3
MyString1COLUMN07MyString2type datetimeMyString3
... ... ...
当我 运行 它在 R
下时,我必须省略 use MYDATABASE;
并确保我连接到正确的数据库,就是这种情况。但是 SQL 语句是有问题的。的输出:
> library(odbc)
> conn <- dbConnect(odbc(), Driver = "SQL Server", Server = "MYSERVER\MYINSTANCE", Database = "MYDATABASE", Trusted_Connection = "True")
> dbGetQuery(conn, "
+ if object_id('tempdb..#mapDT') is not null drop table #mapDT; create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
+ insert into #mapDT SELECT 'varchar', 'type text' UNION ALL SELECT 'datetime', 'type datetime' UNION ALL SELECT 'tinyint', 'int64.Type' UNION ALL SELECT 'int', 'int64.Type' UNION ALL SELECT 'float', 'type number';
+ SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + 'MyString3' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
+ ")
是data frame with 0 columns and 0 rows
。
是不是使用了"temporal tables"(即#mapDT)导致空数据框?如果是这样,有没有办法让 R
and/or Python
到 understand/use 他们?
正如 Gord Thompson 所知,代码应包含 SET NOCOUNT ON;
。因此,
> library(odbc)
> conn <- dbConnect(odbc(), Driver = "SQL Server", Server = "MYSERVER\MYINSTANCE", Database = "MYDATABASE", Trusted_Connection = "True")
> dbGetQuery(conn, "
+ SET NOCOUNT ON; if object_id('tempdb..#mapDT') is not null drop table #mapDT; create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
+ insert into #mapDT SELECT 'varchar', 'type text' UNION ALL SELECT 'datetime', 'type datetime' UNION ALL SELECT 'tinyint', 'int64.Type' UNION ALL SELECT 'int', 'int64.Type' UNION ALL SELECT 'float', 'type number';
+ SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + '},' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
+ ")
在我的例子中不需要行号,所以我也使用了 formals(print.data.frame)$row.names <- FALSE
:
> library(odbc)
> conn <- dbConnect(odbc(), Driver = "SQL Server", Server = "MYSERVER\MYINSTANCE", Database = "MYDATABASE", Trusted_Connection = "True")
> formals(print.data.frame)$row.names <- FALSE
> dbGetQuery(conn, "
+ SET NOCOUNT ON; if object_id('tempdb..#mapDT') is not null drop table #mapDT; create table #mapDT (SqlDatatype varchar (64), MyNewDataType varchar(64));
+ insert into #mapDT SELECT 'varchar', 'type text' UNION ALL SELECT 'datetime', 'type datetime' UNION ALL SELECT 'tinyint', 'int64.Type' UNION ALL SELECT 'int', 'int64.Type' UNION ALL SELECT 'float', 'type number';
+ SELECT COLUMN_NAME, DATA_TYPE, 'MyString1' + COLUMN_NAME + 'MyString2' + m.MyNewDataType + 'MyString3' FROM INFORMATION_SCHEMA.COLUMNS C JOIN #mapDT m on m.SqlDatatype = C.DATA_TYPE WHERE TABLE_NAME = 'MYTABLE';
+ ")
> formals(print.data.frame)$row.names <- TRUE
尽管如此,请考虑避免任何触发 NOCOUNT
的 DML 语句,因为您的临时 table 是不必要的。只需 运行 子查询 JOIN
即可获得更简单、可读、可维护的查询。下面 CONCAT
将 varchar 字段和名称计算列上的 +
替换为别名,OUTPUT
:
SELECT COLUMN_NAME, DATA_TYPE,
CONCAT('MyString1', COLUMN_NAME,
'MyString2', m.MyNewDataType,
'MyString3') AS OUTPUT
FROM INFORMATION_SCHEMA.COLUMNS C
INNER JOIN
( SELECT 'varchar' AS SqlDatatype, 'type text' AS MyNewDataType
UNION ALL SELECT 'datetime', 'type datetime'
UNION ALL SELECT 'tinyint', 'int64.Type'
UNION ALL SELECT 'int', 'int64.Type'
UNION ALL SELECT 'float', 'type number'
) m
ON m.SqlDatatype = C.DATA_TYPE
WHERE TABLE_NAME = 'MYTABLE';