RODBC sqlSave表创建问题

时间:2014-05-28 13:53:23

标签: sql sql-server r sql-server-2008 rodbc

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

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

  1. 他们遇到的问题是不同的,我可以创建表,而他们不能和
  2. 我已经无法合并他们的解决方案,例如在运行sqlSave之前关闭并重新打开连接,
  3. 错误消息不同,唯一的例外是上述两种方式不同的帖子
  4. 我在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读取空表,事实上,我可以。

    更新

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

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

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

      GO

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

      2. 现在sqlUpdate()会看到该表,但它抱怨它需要一个唯一的列

      3. 表示表格中唯一的列是index = colname的唯一列会导致错误,表明该列不存在

      4. 我删除并重新创建了指定主键的表

      5. 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()中的唯一列但出现以下错误:
        2. 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 个答案:

答案 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工作 - 深呼吸,从哪里开始。以下是我为使其工作而做的事情清单:

  • 打开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)

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

Table not found

sqlSave in R

RODBC

答案 2 :(得分:2)

以下是一些经验法则:

  1. 如果事情不顺利,请手动指定列类型,就像@d84_n1nj4建议的那样。
  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)
    
    1. 如果#1不起作用,则继续指定列,但将它们全部指定为VARCHAR(255)。将其视为临时表或临时表,并使用sqlQuery将数据移至下一步,就像@danas.zuokas建议的那样。这应该可以工作,但即使它没有,它会让你更接近金属,如果你需要它,可以让你更好地调试SQL Server Profiler的问题。 &lt; - 是的,如果您仍然遇到问题,可能是由于解析错误或类型转换造成的。
    2. 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的实施和not due to any inherent limitation in T-SQL,R的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抛出上面显示的错误消息之后 - 但它也是空的。