JDBC 创建表并插入亚马逊红移时出错

Posted

技术标签:

【中文标题】JDBC 创建表并插入亚马逊红移时出错【英文标题】:Error in JDBC create table and insert in amazon redshift 【发布时间】:2017-03-15 01:31:29 【问题描述】:

我正在使用 amazon redshift 和 R。我得到了连接。我想创建一些数据库表并通过 R 向其中插入一些数据。但是,我在这样做时遇到了一些问题

# Set the Java Environment
# For 64 bit connections
Sys.setenv(JAVA_HOME='C:\\Program Files\\Java\\jre1.8.0_121')

# For 32 bit connections
#Sys.setenv(JAVA_HOME='C:\\Program Files (x86)\\Java\\jre1.8.0_121')


# Load libraries if they haven't already
library(rJava)
library(RJDBC)

# Get the driver
jdbcDriver <- JDBC(driverClass="com.amazon.redshift.jdbc41.Driver",   
                   classPath="drivers/RedshiftJDBC41-1.2.1.1001.jar")

# Connect to the database
jdbcConnection <- dbConnect(jdbcDriver, 
                            "server",
                            "username", "password")

数据库已连接,没有问题。现在我想创建一个表并将数据插入其中。我使用sqlCreateTablesqlAppendTable 创建数据并将其插入表中。

# Create a table iris, and insert the data into it

sql_required <- sqlCreateTable(jdbcConnection, "iris_table1", iris)

tbl_create <-  dbGetQuery(jdbcConnection, sql_required) 

但是,上面的命令会导致以下错误。

# Error in .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",  : 
#                                Unable to retrieve JDBC result set for CREATE TABLE "iris_table1" (
#                                  "Sepal.Length" DOUBLE PRECISION,
#                                  "Sepal.Width" DOUBLE PRECISION,
#                                  "Petal.Length" DOUBLE PRECISION,
#                                  "Petal.Width" DOUBLE PRECISION,
#                                  "Species" VARCHAR(255)
#                                )
# ([JDBC Driver]com.amazon.dsi.dataengine.impl.DSISimpleRowCountResult 
#   cannot be cast to com.amazon.dsi.dataengine.interfaces.IResultSet)

尽管如此,该表已创建并将通过以下命令列出

sql_required <- "SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG=\'demodata\'"

tables_in_reshift <- dbGetQuery(jdbcConnection, sql_required)
tail(tables_in_reshift, 1)

#   table_name
# 141 iris_table1

我什至可以插入数据

sql_required <- sqlAppendTable(jdbcConnection, "iris_table1", head(iris))


tbl_insert <- dbGetQuery(jdbcConnection, sql_required)

但是,这也会导致以下错误。

# Error in .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",  : 
#                                Unable to retrieve JDBC result set for INSERT INTO "iris_table1"
#                              ("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species")
#                              VALUES
#                              (5.1, 3.5, 1.4, 0.2, 'setosa'),
#                              (4.9, 3, 1.4, 0.2, 'setosa'),
#                              (4.7, 3.2, 1.3, 0.2, 'setosa'),
#                              (4.6, 3.1, 1.5, 0.2, 'setosa'),
#                              (5, 3.6, 1.4, 0.2, 'setosa'),
#                              (5.4, 3.9, 1.7, 0.4, 'setosa')
# ([JDBC Driver]com.amazon.dsi.dataengine.impl.DSISimpleRowCountResult 
# cannot be cast to com.amazon.dsi.dataengine.interfaces.IResultSet)
# 

不过还是会插入数据,如下命令返回6条记录

sql_required <- "SELECT * from iris_table1"

inserted_dat <- dbGetQuery(jdbcConnection, sql_required)


#    sepal.length sepal.width petal.length petal.width species
# 1          4.9         3.0          1.4         0.2  setosa
# 2          4.6         3.1          1.5         0.2  setosa
# 3          5.4         3.9          1.7         0.4  setosa
# 4          5.1         3.5          1.4         0.2  setosa
# 5          4.7         3.2          1.3         0.2  setosa
# 6          5.0         3.6          1.4         0.2  setosa

虽然程序可以运行,但我担心错误。 所以,我的问题是:

试图解释的错误是什么?如何消除它? 有没有更好的方法(更快、更高效)使用RJDBC 创建表并将数据插入redshift?谢谢!

更新 我最初认为运行诸如

之类的命令
sqlCreateTable(jdbcConnection, "iris_table5", iris)

应该足以创建表,但它不创建表也不

sqlAppendTable(jdbcConnection, "iris_table1", head(iris))

将数据附加到数据库表中。

【问题讨论】:

【参考方案1】:

我遇到了同样的错误。我在 SQL 工作台中运行查询。所以这绝对不是R的问题。 它看起来像一个红移错误。我还更改了 JDBC 版本,但仍然出现相同的错误。与使用相同 JDBC 版本的同事一起测试了该查询,这对她来说非常有效。 我认为 redshift 中的首选语法是 CTAS 语句。同一查询的 CTAS 版本运行良好。我的解决方案是切换到 CTAS 语法。 https://docs.aws.amazon.com/redshift/latest/dg/r_CTAS_examples.html

【讨论】:

【参考方案2】:

以下两个命令:

sql_required <- sqlCreateTable(jdbcConnection, "iris_table1", iris)
tbl_create <-  dbGetQuery(jdbcConnection, sql_required)

创建表只需要第一次调用。来自documentation for dbGetQuery():

此函数仅适用于 SELECT 查询。

但是您不是在进行选择,而是在创建一个表。您在此处插入数据的调用也是如此:

sql_required <- sqlAppendTable(jdbcConnection, "iris_table1", head(iris))

因此,您应该只删除那些对dbGetQuery() 的不必要调用,这应该可以解决这些错误。

我不认为这是必要的,但您可能需要致电 dbCommit() 来关闭交易:

dbCommit(jdbcConnection)

【讨论】:

谢谢!我有同样的看法,我最初确实尝试过,但那些没有创建表,也没有附加数据。我已更新问题以澄清这一点。 @discipulus 根据我的阅读,这应该没有必要。听起来好像没有提交事务。您可以尝试在 DML 语句之后使用 dbCommit() 有趣!它没有帮助。 dbCommit(jdbcConnection) 返回 true,但是当我运行查询时:inserted_dat &lt;- dbGetQuery(jdbcConnection, "SELECT * from iris_table1"),它返回错误 Error in .jcall(conn@jc, "Ljava/sql/Statement;", "createStatement") : java.sql.SQLException: [Amazon][JDBC](10040) Cannot use commit while Connection is in auto-commit mode. 第二次运行相同的命令有效,但数据未附加到表中。 我认为你对 Redshift 有问题,而不是 R。你应该查看 Redshift 的文档。 如果关闭 R 会话,下次检查时数据是否会出现在表格中?【参考方案3】:

我有同样的错误。如果您查看软件包文档,您会发现:

dbSendQuerydbSendUpdate 向数据库提交 SQL 查询。两者的区别仅在于dbSendUpdateDBML 查询一起使用,因此不返回任何结果集。

所以使用 dbSendUpdate 代替 dbSendQuery 对我有用。

【讨论】:

以上是关于JDBC 创建表并插入亚马逊红移时出错的主要内容,如果未能解决你的问题,请参考以下文章

将镶木地板文件加载到红移时如何格式化时间戳字段?

如何使用 Elasticbeanstalk 在亚马逊 RDS 中删除表并重新创建?

在 sql2o 中插入时出错

如何在亚马逊红移谱加载外部表时跳转结束几张唱片?

使用 java 创建具有约束的配置单元表并使用 jdbc 程序检查配置单元表的列约束

自动创建表并从 json 文件插入数据