我在使用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
最后,请注意我在没有append = TRUE的情况下以及创建新表时,以及使用和不使用rownames选项时都尝试了此操作。
来自Freenode #R的Mr.Flick让我检查一下我是否可以使用sqlQuery读取空表,事实上,我可以。更新
我已经通过以下步骤更加接近了:
table =
或tablename =
语句中指定表的路径 GO
CREATE TABLE [dbo].[testing123](
[Person_DIMKey] [int] NULL
) ON [PRIMARY]
GO
在R中,我使用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在显示时重置列表的编号几次。如果有人能帮我清理这篇文章的这一方面,我会很感激。
答案 0 :(得分:7)
重新阅读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
。
答案 1 :(得分:6)
经过几个小时的工作,我终于能够在指定表名时让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)
然后我的脑袋脱落了,因为它有效!我真的希望这有助于前进的人。以下是帮助我达到这一点的链接:
答案 2 :(得分:2)
以下是一些经验法则:
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的问题。 &lt; - 是的,如果您仍然遇到问题,可能是由于解析错误或类型转换造成的。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
。 答案 3 :(得分:1)
除了之前发布的一些回答,这是我的解决方法。注意:我将此作为小型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)
答案 4 :(得分:1)
我们遇到了同样的问题,经过一些测试后,我们只是通过在模式和表名引用中不使用方括号解决了这个问题。
即。而不是写
table = "[Jason].[dbo].[df]"
改为写
table = "Jason.dbo.df"
感谢现在已经过了原来的问题,但是对于其他随后绊倒这个问题的人来说,这就是我们解决问题的方法。作为参考,我们通过将一个简单的1项数据帧写入一个新表来找到这一点,在SQL中检查时包含表名中的方括号。
答案 5 :(得分:0)
我遇到了同样的问题 - 我发现它的方法是使用常规CREATE TABLE
SQL语法创建一个空表,然后通过sqlSave
附加到它。出于某种原因,当我按照你的方式尝试时,我实际上可以在MSSQL数据库中看到表名 - 即使在R抛出上面显示的错误消息之后 - 但它也是空的。