[英]RODBC sqlSave table creation problems
我在使用 RODBC 的 sqlSave 创建表时遇到问题(或者更准确地说,将数据写入创建的表)。
这与现有的 sqlSave 问题/答案不同,因为
我在 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 读取空表,确实可以。
更新
我通过以下步骤更接近了:
table =
或tablename =
语句中指定表的路径GO
CREATE TABLE [dbo].[testing123](
[Person_DIMKey] [int] NULL
) ON [PRIMARY]
GO
在 RI 中使用sqlUpdate
和我的新 ODBC 连接并且表名周围没有括号
现在 sqlUpdate() 看到了表,但是它抱怨它需要一个唯一的列
指示表中唯一的列是index = colname
的唯一列会导致错误,指出该列不存在
我删除并重新创建了指定主键的表,
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 界面)
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 工作——深呼吸,从哪里开始。 这是我为使其工作而做的事情列表:
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)
然后我的头掉了下来,因为它有效! 我真的希望这有助于有人前进。 以下是帮助我达到这一点的链接:
重新阅读 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 中检查时,该表包含表名中的方括号。
以下是一些经验法则:
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)
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')
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.