Почему это работает в Microsoft SQL Server Management Studio, но не в R? - PullRequest
0 голосов
/ 19 февраля 2020

Я получил это 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 -соглашение проблематично c. Вывод:

> 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 понять / использовать их?

Ответы [ 2 ]

2 голосов
/ 19 февраля 2020

Тем не менее, избегайте любых операторов DML, которые запускают NOCOUNT, поскольку ваша временная таблица не нужна. Просто запустите подзапрос 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';
0 голосов
/ 19 февраля 2020

Как знает Горд Томпсон, код должен включать 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
...