【问题标题】:R: Insert csv-file into database using RJDBCR:使用 RJDBC 将 csv 文件插入数据库
【发布时间】:2019-04-06 15:51:47
【问题描述】:

由于 RJDBC 是我能够在 Ubuntu 上运行的唯一软件包,我正在尝试使用它来INSERT CSV 文件 进入数据库。

我可以做以下工作:

# Connecting to database
library(RJDBC)
drv <- JDBC('com.microsoft.sqlserver.jdbc.SQLServerDriver', 'drivers/sqljdbc42.jar', identifier.quote="'")
connection_string <- "jdbc:sqlserver://blablaserver;databaseName=testdatabase"
ch <- dbConnect(drv, connection_string, "username", "password")

# Inserting a row
dbSendQuery(ch, "INSERT INTO cpr_esben.CPR000_Startrecord (SORTFELT_10,OPGAVENR,PRODDTO,PRODDTOFORRIG,opretdato) VALUES ('TEST', 123, '2012-01-01', '2012-01-01', '2012-01-01')")

插入有效。接下来,我尝试使用相同的数据创建 CSV 文件的 INSERT,该数据由默认的“选项卡”分隔,并且我正在使用 Windows。

# Creating csv
df <- data.frame(matrix(c('TEST', 123, '2012-01-01', '2012-01-01', '2012-01-01'), nrow = 1), stringsAsFactors = F)
colnames(df) <- c("SORTFELT_10","OPGAVENR","PRODDTO","PRODDTOFORRIG","opretdato")
class(df$SORTFELT_10) <- "character"
class(df$OPGAVENR) <- "character"
class(df$PRODDTO) <- "character"
class(df$PRODDTOFORRIG) <- "character"
class(df$opretdato) <- "character"
write.table(df, file = "test.csv", col.names = FALSE, quote = FALSE)

# Inserting CSV to database
dbSendQuery(ch, "INSERT cpr_esben.CPR000_Startrecord FROM 'test.csv'")

Unable to retrieve JDBC result set for INSERT cpr_esben.CPR000_Startrecord FROM 'test.csv' (Incorrect syntax near the keyword 'FROM'.)

在尝试插入 csv 文件时,您对我做错了什么有什么建议吗?我没有收到 Incorrect syntax near the keyword 'FROM' 错误?

【问题讨论】:

    标签: r insert bulkinsert rjdbc


    【解决方案1】:

    RJDBC 是建立在 DBI 之上的,它有很多有用的功能来完成这样的任务。你想要的是dbWriteTable。语法是:

    dbWriteTable(ch, 'cpr_esben.CPR000_Startrecord', df, append = TRUE)
    

    并将替换您的 write.table 行。

    我对 RJDBC 不太熟悉,但我认为您的 sendQuery 的问题是您在 SQL 语句中引用 test.csv,它没有找到您使用 write.table 创建的文件作为范围该 SQL 语句不在您的工作目录中。

    【讨论】:

    • 我在使用“写表”方法时遇到的问题是我需要在数据库中创建新表的权限(即使我选择了“append=TRUE”)。我之所以选择在 SQL 查询中引用我的 csv 文件,是因为我受到这篇文章 stackoverflow.com/questions/19190744/… 的启发
    • 如果你没有写权限,什么都行不通,你到底有什么权限?
    • 同意穆迪。如果您想复制您链接的示例,您还需要反映他们使用的完整路径结构。
    • 我有写权限,但我没有创建新表的权限。
    • DBI::dbWriteTable(..., append=TRUE) 是如何创建新表的?通常,create=TRUE,append=TRUE 是直接矛盾的并且会出错。
    【解决方案2】:

    如果您根据数据创建声明会怎样?比如:

    # Data from your example
    df <- data.frame(matrix(c('TEST', 123, '2012-01-01', '2012-01-01', '2012-01-01'), nrow = 1), stringsAsFactors = F)
    colnames(df) <- c("SORTFELT_10","OPGAVENR","PRODDTO","PRODDTOFORRIG","opretdato")
    class(df$SORTFELT_10) <- "character"
    class(df$OPGAVENR) <- "character"
    class(df$PRODDTO) <- "character"
    class(df$PRODDTOFORRIG) <- "character"
    class(df$opretdato) <- "character"
    
    # Formatting rows to insert into SQL statement
    rows <- apply(df, 1, function(x){paste0('"', x, '"', collapse = ', ')})
    rows <- paste0('(', rows, ')')
    
    # SQL statement
    statement <- paste0(
      "INSERT INTO cpr_esben.CPR000_Startrecord (", 
      paste0(colnames(df), collapse = ', '), 
      ')',
      ' VALUES ',
      paste0(rows, collapse = ', ')
    )
    
    dbSendQuery(ch, statement)
    

    这应该适用于您的 df 中的任意数量的行

    【讨论】:

    • 如果你有大数据框,这是一个非常丑陋的解决方案,但我最终做了类似的事情。我最终将 CSV 文件写入文件,然后使用 BCP 上传数据。
    • 如果没有更好的解决方案出现,那么我只会给你解决方案,因为它确实可以解决问题。
    • 是的,这很难看,但我相信这是使用dbSendQuery 函数的唯一方法。 dbWriteTable 在幕后做了类似的事情,但你看不到它产生的丑陋声明 xD
    【解决方案3】:

    您是否尝试过如下将文件直接加载到数据库中。

    library(RJDBC)
    drv <- JDBC("connections")      
    conn <- dbConnect(drv,"...")
    
    query = "LOAD DATA INFILE 'test.csv' INTO TABLE test"
    dbSendUpdate(conn, query)
    

    您也可以尝试在末尾包含其他语句,例如用于列的分隔符,例如用于 .txt 文件的 "|" 和用于 csv 文件的 ","

    【讨论】:

      猜你喜欢
      • 2022-11-29
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      相关资源
      最近更新 更多