【问题标题】:Why does using a prepared statement fail with nulls and succed with GStrings?为什么使用准备好的语句会因空值而失败,而使用 G 字符串会成功?
【发布时间】:2010-09-25 09:24:45
【问题描述】:

问题简述:

当尝试使用准备好的语句和 groovy.sql.Sql 插入包含几个空列的行时会发生这种情况:

groovy:000> val
===> [123123123, 2, null, 0, 0, , null, , 1213020112511801, 1283425009158952, 1, 2, null, 0, 0, , null, , 1213020112511801, 1283425009158952]
groovy:000> destSql.execute "insert into my_table values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", val
ERROR java.sql.SQLException: Type is not supported.
        at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException (Unknown Source)
        at org.apache.derby.client.am.SqlException.getSQLException (Unknown Source)
        at org.apache.derby.client.am.PreparedStatement.setObject (Unknown Source)
        at groovysh_evaluate.run (groovysh_evaluate:3)
        ...
groovy:000> 

destSql.dataSet("my_table").add valueMap 得到了类似的结果。

这是尝试插入与 GString 相同的行时发生的情况:

groovy:000> destSql.execute "insert into my_table values (${val[0]}, ${val[1]}, ${val[2]}, ${val[3]}, ${val[4]}, ${val[5]}, ${val[6]}, ${val[7]}, ${val[8]}, ${val[9]})"
===> false
groovy:000> 

现在,我了解到使用准备好的语句插入空值存在问题(如文档所述,例如 herehere)。

我想了解的是:

1) 我很难相信在准备好的语句中插入空值是不可能,那么为什么有时会导致问题呢?不完善的 JDBC 驱动程序、数据库引擎?

2) 为什么使用 GString 的示例有效?照着同样的逻辑,空列的信息不还是要输入的吗?

【问题讨论】:

    标签: sql groovy null derby


    【解决方案1】:

    如果包含您遇到的实际异常,您将获得更好的响应。您可以在 Derby 服务器的 derby.log 文件中找到异常,也可以修改应用程序以打印整个异常链,而不仅仅是客户端最外层的异常:http://wiki.apache.org/db-derby/UnwindExceptionChain

    如果没有看到实际的异常,很难为您提供帮助,但我大胆猜测您看到的是https://issues.apache.org/jira/browse/DERBY-1938

    【讨论】:

    • 这是一个很好的链接 Bryan,我相信它很好地解释了为什么问题是间歇性的(驱动程序、RDBMS 和使用模式的某些组合)以及为什么在我的情况下使用准备好的语句不起作用。
    • 您知道为什么 GStrings 方法有效吗?我浏览了 groovy.sql.Sql 源代码,看到它还试图创建一个准备好的语句......传递了“对象”而不是“字符串”值,我无法想象它会如何工作,但 derby 会拒绝具有空值的准备好的语句...?
    • 我很确定,对于许多版本,PreparedStatement.setString(N, null) 在 Derby 中运行良好,但 PreparedStatement.setObject(N, null) 失败了。我相信这是 DERBY-1938 解决的问题的本质。因此,根据 Groovy 程序使用的确切数据类型,Groovy SQL 库有时会调用 setString,有时会调用 setObject?
    • 我不会说这是可能的原因,但我相信你已经正确回答了谜题的另一部分(为什么它在我的情况下不起作用)所以我会包装它在这里。
    【解决方案2】:

    gstring 示例正在运行,因为如果数组元素为空,代码 ${val[0]} 将返回 null

    如果您在问题中插入的代码是正确的,那么你们中的一些元素没有null 值...这只是一个猜测

    【讨论】:

    • 您可以看到我尝试插入的值:它们代表一个有效记录,其中几个字段设置为空。 ${val[0]} 确实会返回 null,但为什么 Derby 接受它而不接受 null 值作为准备好的语句的参数?
    猜你喜欢
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多