繁体   English   中英

RODBC sqlSave 表创建问题

[英]RODBC sqlSave table creation problems

我在使用 RODBC 的 sqlSave 创建表时遇到问题(或者更准确地说,将数据写入创建的表)。

这与现有的 sqlSave 问题/答案不同,因为

  1. 他们遇到的问题是不同的,我可以创建表而他们不能并且
  2. 我已经没有成功地合并他们的解决方案,例如在运行 sqlSave 之前关闭和重新打开连接,也
  3. 错误信息是不同的,唯一的例外是上述两种方式不同的帖子

我在 Windows RDP 上使用 MS SQL Server 2008 和 64 位 R。

我有一个简单的数据框,其中只有 1 列包含 3、4 或 5 位整数。

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

当我尝试使用 sqlSave 时,没有数据写入表中。 此外,一条错误消息使它听起来像是无法创建该表,尽管该表实际上是用 0 行创建的。

根据我发现的建议,我尝试在运行 sqlSave 之前关闭并重新打开 RODBC 连接。 即使我使用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错误table not found on channel

最后,请注意,我在没有 append = TRUE 的情况下以及在创建新表时以及使用和不使用 rownames 选项时也尝试了此操作。

Freenode's #R 的 Mr.Flick 让我检查是否可以使用 sqlQuery 读取空表,确实可以。

更新

我通过以下步骤更接近了:

  1. 我创建了一个 ODBC 连接,它直接连接到 SQL Server 中的数据库,而不是仅连接到默认(主)数据库,然后在table =tablename =语句中指定表的路径
  2. 在 SQL Server Management Studio 中创建表如下

GO

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

GO

  1. 在 RI 中使用sqlUpdate和我的新 ODBC 连接并且表名周围没有括号

  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

它生成了一个名为PK__jive_BNR__2754EC2E30F848ED的主键和索引(根据 SQL Sever Management Studio 的 GUI 界面)

  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 会在显示列表时多次重置列表的编号。 如果有人能帮我清理这篇文章的那个方面,我将不胜感激。

经过数小时的工作,我终于能够在指定表名的同时让 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.characteras.Date更新了我的数据框类类型以匹配上面列出的数据类型。
  • 我已经创建了这个表,因为我已经工作了几个小时,所以我不得不使用sqlDrop(myconn2, "##R_Claims_Data")删除该表。
  • 然后我跑了: sqlSave(myconn2, MainClmDF2, tablename = "##R_Claims_Data", verbose=TRUE, rownames= FALSE, varTypes=columnTypes)

然后我的头掉了下来,因为它有效! 我真的希望这有助于有人前进。 以下是帮助我达到这一点的链接:

未找到表

R中的sqlSave

RODBC

重新阅读 RODBC 小插图后,这是一个有效的简单解决方案:

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语句之前。

我们遇到了同样的问题,经过一些测试,我们通过在架构和表名引用中不使用方括号来解决。

即而不是写作

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

而是写

table = "Jason.dbo.df"

欣赏这现在已经超越了最初的问题,但对于随后遇到这个问题的其他人来说,这就是我们解决它的方式。 作为参考,我们通过将一个简单的 1 项数据框写入一个新表发现了这一点,当在 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.zuokas建议的那样。 这应该有效,但即使无效,它也会让您更接近实际情况,并使您在需要时可以更好地使用 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 中的任何固有限制,R 的logical类型(即[TRUE, FALSE] )不会转换为 T-SQL 的BIT类型(即 [1, 0]),所以不要尝试这个。 在 R 层将logical类型转换为 [1, 0] 或将其作为VARCHAR(5)下放到 SQL 层并在 SQL 层将其转换为BIT

除了之前发布的一些回答之外,这是我的解决方法。 注意:我将此用作小型 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;")

最后,在没有 tablename 参数的情况下运行 sqlSave,这将创建表并用您的数据框填充它:

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

我遇到了同样的问题——我发现的方法是使用常规的CREATE TABLE SQL 语法创建一个空表,然后通过sqlSave附加到它。 出于某种原因,当我按照你的方式尝试时,我实际上可以在 MSSQL 数据库中看到表名——即使在 R 抛出你上面显示的错误消息之后——但它会是空的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM