Проблемы создания таблицы RODBC sqlSave

у меня возникли проблемы с созданием таблицы с помощью SQLSAVE RODBC (или, точнее, записи данных в созданную таблицу).

это отличается от существующего вопроса/ответов sqlSave, как

  1. проблемы, которые они испытывали, были разными, я могу создавать таблицы, тогда как они не могли и
  2. я уже неудачно включил их решения, такие как закрытие и повторное открытие соединения перед запуском sqlSave, также
  3. сообщение об ошибке отличается, за единственным исключением является сообщение, которое отличалось выше 2 способами

я использую MS SQL Server 2008 и 64-разрядный R в Windows RDP.

у меня есть простой фрейм данных только с 1 столбцом, полным 3, 4 или 5-значными целыми числами.

> head(df)
                        colname
1                           564
2                          4336
3                         24810
4                         26206
5                         26433
6                         26553

когда я пытаюсь использовать sqlSave, данные не записываются в таблицу. Кроме того, сообщение об ошибке звучит как таблица не может быть создана хотя таблица фактически создается с 0 строками.

основываясь на предложении, которое я нашел, я попытался закрыть и снова открыть соединение RODBC прямо перед запуском sqlSave. Хотя я использую append = TRUE, Я попытался сбросить таблицу, прежде чем делать это, но это ни на что не влияет.

> sqlSave(db3, df, table = "[Jason].[dbo].[df]", append = TRUE, rownames = FALSE)
Error in sqlSave(db3, df, table = "[Jason].[dbo].[df]",  : 
  42S01 2714 [Microsoft][ODBC SQL Server Driver][SQL Server]There is already 
an object named 'df' in the database.
[RODBC] ERROR: Could not SQLExecDirect 'CREATE TABLE [Jason].[dbo].[df]  
("df" int)'

я также попытался использовать sqlUpdate () в таблице после ее создания. Не имеет значения, создаю ли я его в R или SQL Server Management Studio, я получаю ошибку table not found on channel

наконец, обратите внимание, что я также пробовал это без добавления = TRUE и при создании новой таблицы, а также с опцией rownames и без нее.

Мистер Флик из Freenode #R заставил меня проверить, могу ли я читать в пустой таблице с помощью sqlQuery, и действительно, я могу.

обновление

я стал немного ближе со следующими шагами:

  1. я создал соединение ODBC, которое идет непосредственно к моему База данных в SQL Server, а не только в БД по умолчанию (Master), а затем указывает путь к таблице в table = или tablename = заявления
  2. создал таблицу в среде SQL Server Management Studio следующим образом

GO

CREATE TABLE [dbo].[testing123]( [Person_DIMKey] [int] NULL ) ON [PRIMARY]

GO

  1. в R я использовал sqlUpdate С моим новым соединением ODBC и без скобок вокруг tablename

  2. теперь sqlUpdate () видит таблицу, однако она жалуется, что ей нужен уникальный столбец

  3. указывает, что единственным столбцом в таблице является уникальный столбец с index = colname приводит к ошибке, говоря, что столбец не существует

  4. я отбросил и воссоздал таблицу, указав первичный ключ,

GO

CREATE TABLE [dbo].[jive_BNR_Person_DIMKey]( [jive_BNR_Person_DIMKey] [int] NOT NULL PRIMARY KEY ) ON [PRIMARY]

GO

который сгенерировал как первичный ключ, так и индекс (согласно интерфейсу GUI SQL Sever Management Studio) с именем PK__jive_BNR__2754EC2E30F848ED

  1. я уточнил этот индекс/ключ как уникальный столбец в sqlUpdate() но я получаю следующую ошибку:

Error in sqlUpdate(db4, jive_BNR_Person_DIMKey, tablename = "jive_BNR_Person_DIMKey", : index column(s) PK__jive_BNR__2754EC2E30F848ED not in database table

для записи я указывал правильное имя столбца (не "colname") для индекса; спасибо MrFlick за запрос разъяснения.

кроме того, эти шаги пронумерованы от 1 до 7 в моем сообщении, но StackOverflow сбрасывает нумерацию списка несколько раз, когда он отображается. Если кто-нибудь может помочь мне очистить этот аспект этого сообщения, я был бы признателен.

6 ответов


после перечитывания RODBC vingette и вот простое решение, которое сработало:

sqlDrop(db, "df", errors = FALSE)
sqlSave(db, df)

сделано.

после экспериментов с этим намного больше в течение нескольких дней, кажется, что проблемы возникли из-за использования дополнительных опций, особенно table = или, что эквивалентно, tablename =. Это должны быть допустимые параметры, но каким-то образом им удается вызвать проблемы с моей конкретной версией RStudio ((Windows, 64 бит, настольная версия, текущая сборка), R (Windows, 64 бит, v3) и/или MS SQL Server 2008.

sqlSave(db, df) также будет работать без sqlDrop(db, "df") если таблица никогда не существовало, но в качестве лучшей практики, я пишу try(sqlDrop(db, "df", errors = FALSE), silent = TRUE) прежде всего sqlSave заявления в моем коде.


после нескольких часов работы над этим я, наконец, смог заставить sqlSave работать, указав имя таблицы-глубокий вдох, с чего начать. Вот список вещей, которые я сделал, чтобы заставить это работать:

  • откройте 32-разрядный администратор ODBC и создайте пользовательский DSN и настройте его для конкретной базы данных. В моем случае я создаю глобальную временную таблицу, поэтому я связался с tempdb. Используйте это имя соединения в своем odbcConnection(Name). Вот мой код myconn2 <- odbcConnect("SYSTEMDB").
  • затем я определил мои типы данных со следующим кодом:columnTypes <- list(Record = "VARCHAR(10)", Case_Number = "VARCHAR(15)", Claim_Type = "VARCHAR(15)", Block_Date = "datetime", Claim_Processed_Date = "datetime", Status ="VARCHAR(100)").
  • затем я обновил типы классов фрейма данных с помощью as.character и as.Date для соответствия типам данных, перечисленным выше.
  • я уже создал таблицу, так как я работал над ней в течение нескольких часов, поэтому мне пришлось удалить таблицу с помощью sqlDrop(myconn2, "##R_Claims_Data").
  • затем я побежал: sqlSave(myconn2, MainClmDF2, tablename = "##R_Claims_Data", verbose=TRUE, rownames= FALSE, varTypes=columnTypes)

затем моя голова отвалилась, потому что это сработало! Я очень надеюсь, что это поможет кому-то двигаться вперед. Вот ссылки, которые помогли мне сделать до этого момента:

таблица не найдена

sqlSave в R

RODBC


в дополнение к некоторым ответам, опубликованным ранее, вот мой обходной путь. Примечание: Я использую это как часть небольшого процесса ETL, и таблица назначения в БД отбрасывается и воссоздается каждый раз.

в основном вы хотите назвать свой фрейм данных, как называется таблица назначения:

RodbcTest <- read.xlsx('test.xlsx', sheet = 4, startRow = 1, colNames = TRUE, skipEmptyRows = TRUE)

затем убедитесь, что строка подключения включает целевую базу данных (а не только сервер):

conn <- odbcDriverConnect(paste("DRIVER={SQL Server};Server=localhost\sqlexpress;Database=Charter;Trusted_Connection=TRUE"))

после этого я запускаю простой sqlQuery, который условно удаляет таблицу, если она существует:

sqlQuery(conn, "IF OBJECT_ID('Charter.dbo.RodbcTest') IS NOT NULL DROP TABLE Charter.dbo.RodbcTest;")

затем, наконец, запустите sqlSave без параметра tablename, который создаст таблицу и заполнит ее вашим фреймом данных:

sqlSave(conn, RodbcTest, safer = FALSE, fast = TRUE)

у нас была такая же проблема, что после небольшого тестирования мы решили просто не использовать квадратные скобки в ссылке на имя схемы и таблицы.

т. е. вместо того, чтобы писать

table = "[Jason].[dbo].[df]"

вместо того, чтобы писать

table = "Jason.dbo.df"

оцените, что это уже давно прошло первоначальный вопрос, но только для тех, кто впоследствии натыкается на эту проблему, вот как мы ее решили. Для справки, мы узнали это, написав простой 1 пункт dataframe к новой таблице, которая при проверке в SQL содержала квадратные скобки в имени таблицы.


вот несколько правил:

  1. если что-то не работает, то вручную укажите типы столбцов так же, как @d84_n1nj4 предложил.

columnTypes <- list(Record = "VARCHAR(10)", Case_Number = "VARCHAR(15)", Claim_Type = "VARCHAR(15)", Block_Date = "datetime", Claim_Processed_Date = "datetime", Status ="VARCHAR(100)")

sqlSave(myconn2, MainClmDF2, tablename = "##R_Claims_Data", verbose=TRUE, rownames= FALSE, varTypes=columnTypes)

  1. если #1 не работает, продолжайте указывать столбцы, но укажите их все как VARCHAR(255). Рассматривайте это как временную или промежуточную таблицу и перемещайте данные с помощью sqlQuery С вашим следующим шагом, так же, как @danas.Зуокас!--15--> предложил. Это должно работать, но даже если это не так, это приближает вас к металлу и ставит вас в лучшее положение для отладки проблемы с SQL Server Profiler, если вам это нужно.

columnTypes <- list(Record = "VARCHAR(255)", Case_Number = "VARCHAR(255)", Claim_Type = "VARCHAR(255)", Block_Date = "VARCHAR(255)", Claim_Processed_Date = "VARCHAR(255)", Status ="VARCHAR(255)")

sqlSave(myconn2, MainClmDF2, tablename = "##R_Claims_Data", verbose=TRUE, rownames= FALSE, varTypes=columnTypes)

sqlQuery(channel, 'insert into real_table select * from R_Claims_Data')

  1. из-за реализации RODBC и не из-за любого неотъемлемого ограничения в T-SQL, Р logical тип (т. е. [TRUE, FALSE]) не будет преобразование в T-SQL BIT введите (т. е. [1, 0]), поэтому не пытайтесь это сделать. Либо преобразовать logical введите [1, 0] в слое R или перенесите его на уровень SQL как VARCHAR(5) и преобразовать его в BIT в слое SQL.

я столкнулся с той же проблемой-так, как я нашел вокруг нее, чтобы создать пустую таблицу с помощью regular CREATE TABLE синтаксис SQL, а затем добавьте к нему через sqlSave. По какой - то причине, когда я попробовал это по - вашему, я мог видеть имя таблицы в базе данных MSSQL-даже после того, как R выбросил сообщение об ошибке, которое вы показали выше, - но оно было бы пустым.