【问题标题】:Is there a way to make a JDBC prepared statement that reads from R dataframe directly?有没有办法制作一个直接从 R 数据帧读取的 JDBC 准备语句?
【发布时间】:2019-09-13 23:54:24
【问题描述】:

我正在尝试使用 RJDBC 使用 FastLoad 实用程序从 R 数据帧读取到 Teadata 中的表。是否可以编写一个准备好的语句并使用 .jcall 直接从数据帧中读取?

据我所知,我已经注意到/尝试了一些事情,但似乎没有直接从数据帧中读取:

http://developer.teradata.com/blog/amarek/2013/11/how-to-use-jdbc-preparedstatement-batch-insert-with-r-0

Teradata-jdbc: What's the point of using Fastload if java has memory limitations?

http://developer.teradata.com/connectivity/articles/speed-up-your-jdbcodbc-applications

https://downloads.teradata.com/blog/ulrich/2013/11/a-wider-test-case-on-r-jdbc-fastload

更新 .... Parfait 的以下建议对我有用:

library(RJDBC)

con <- dbConnect(... connection details ...)

dbSendUpdate (con, "Drop Table Dl_ho_test.Iris_R")

dbSendUpdate (con, "Create Multiset Table Dl_Ho_Test.Iris_R (
                      Sepal_Length float
                    , Sepal_Width float
                    , Petal_Length float
                    , Petal_Width float
                    , Species varchar(10)
                    ) No Primary Index;"
)

## def functions
myinsert <- function(col1, col2, col3, col4, col5){
  .jcall(ps, "V", "setDouble", as.integer(1), col1)
  .jcall(ps, "V", "setDouble", as.integer(2), col2)
  .jcall(ps, "V", "setDouble", as.integer(3), col3)
  .jcall(ps, "V", "setDouble", as.integer(4), col4)
  .jcall(ps, "V", "setString", as.integer(5), as.character(col5))
  .jcall(ps, "V", "addBatch")
}

## prepare
ps = .jcall(con@jc, "Ljava/sql/PreparedStatement;", "prepareStatement", "insert into Dl_Ho_Test.Iris_R(?,?,?,?,?)")

## batch insert
for(n in 1:nrow(iris)) {
  myinsert(iris$Sepal.Length[n], iris$Sepal.Width[n], iris$Petal.Length[n], iris$Petal.Width[n], iris$Species[n])
}

## apply & commit
.jcall(ps, "[I", "executeBatch")
dbCommit(con)
.jcall(ps, "V", "close")
.jcall(con@jc, "V", "setAutoCommit", TRUE)

【问题讨论】:

  • @Parfait,谢谢你的帮助,很好的建议。我编辑了上面的,现在我是 iris 数据集,以使共享更容易。我收到错误“.jcall (ps, "V", "setFloat, 1, col1) 中的错误:未找到带有签名 (DD)v 的方法 setFloat。我倾向于觉得 for(n in 1:nrow(iris)) 是问题.... JDBC 可以识别这样的数据框吗?
  • 请在我的回答下包含此评论。如果您的编辑没有在主页上出现,我会完全错过它。看来setFloat 方法是这里的问题。尝试使用 double 列类型的 setDouble

标签: r dataframe jdbc teradata rjdbc


【解决方案1】:

在最后一个link之后,考虑保持函数形式并循环遍历数据框行:

## def functions
myinsert <- function(col1, col2, col3){
  .jcall(ps, "V", "setInt", 1, col1)
  .jcall(ps, "V", "setInt", 2, col2)
  .jcall(ps, "V", "setString", 3, col3)

  .jcall(ps, "V", "addBatch")
}

## prepare
ps = .jcall(con@jc, "Ljava/sql/PreparedStatement;", "prepareStatement", 
            "insert into Some_Test_Table(?,?,?)")

## batch insert
for(n in 1:nrow(my.data.frame)) { 
  myinsert(my.data.frame$col1[n], my.data.frame$col2[n], my.data.frame$col3[n])
}

## apply & commit
.jcall(ps, "[I", "executeBatch")
dbCommit(con)
.jcall(ps, "V", "close")
.jcall(conn@jc, "V", "setAutoCommit", TRUE)

【讨论】:

  • 抱歉,我是 Stack Overflow 的新手(更不用说 R 和 JDBC)了。您的建议对所有这些数字字段都很有效!但是现在我遇到了第 5 列的问题,它是一个字符串类型的字段。修改后的代码和错误信息在上面。我也尝试了 setAsciiStream,但这似乎也有错误
  • iris 中的Species 列是因子列。尝试使用 as.character() 进行投射。
  • 以上代码效果很好!非常感谢您的快速帮助!
猜你喜欢
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2021-02-16
  • 2020-03-27
  • 2013-06-25
相关资源
最近更新 更多