【问题标题】:Why does this work under Microsoft SQL Server Management Studio but not under R?为什么这在 Microsoft SQL Server Management Studio 下有效,但在 R 下无效?
【发布时间】:2020-02-19 09:40:31
【问题描述】:

我收到了这条 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

是使用“临时表”(即#mapDT)导致空数据框的原因吗?如果是这样,有没有办法让R 和/或Python 理解/使用它们?

【问题讨论】:

标签: sql r odbc ssms rodbc


【解决方案1】:

尽管如此,请考虑避免任何触发NOCOUNT 的 DML 语句,因为您的临时表是不必要的。只需运行子查询JOIN 即可获得更简单、可读、可维护的查询。下面的CONCAT 用别名OUTPUT 替换了varchar 字段和名称计算列上的+

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';

【讨论】:

  • 好奇的@scjorge,这个解决方案有帮助吗?避免使用临时表是最佳选择。你甚至可以使用CTE
  • 是的!此语句以更优雅的方式生成所需的输出...在 R 和 Python 下运行。可能我应该更改我的问题的标题以将重点放在这个答案上?嗯..
  • 有时在 StackOverflow 上,我们会建议比简单修复原始问题更好的答案。未来的读者是我们观众的一部分。但快乐编码!
  • 好。然后我必须请您合并两个答案以将一个标记为已接受的答案。我无法合并它们,因为 StackExchange 不允许编辑太重。 :)
【解决方案2】:

正如 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 &lt;- 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

【讨论】:

    猜你喜欢
    • 2018-04-01
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多