使用“?::TIMESTAMP_NTZ”在查询中指定类型时,Snowflake JDBC 批量插入失败并显示“绑定变量?未设置”
Posted
技术标签:
【中文标题】使用“?::TIMESTAMP_NTZ”在查询中指定类型时,Snowflake JDBC 批量插入失败并显示“绑定变量?未设置”【英文标题】:Snowflake JDBC batch insert fails with "Bind variable ? not set" when specifying type in the query using "?::TIMESTAMP_NTZ" 【发布时间】:2020-05-07 01:55:28 【问题描述】:我们正在使用 JDBC 驱动程序连接到 Snowflake 并执行插入操作。 表可以有多个时间戳列,这意味着单个插入查询可能必须同时处理 timestamp_ntz 和 timestamp_ltz。
当我们在查询中指定类型同时绑定值如下时,它工作正常
INSERT INTO <TABLENAME> VALUES(?::TIMESTAMP_NTZ, ?::TIMETAMP_LTZ)
但是,当我们尝试使用 addBatch() 和 executeBatch() 时,它会失败并显示“绑定变量?未设置”
示例程序 -
try (Connection con = getConnection())
con.createStatement().execute("create or replace table Test_TSNTZ(t1 TIMESTAMPNTZ)");
try (PreparedStatement ps = con.prepareStatement("insert into Test_TSNTZ values (? ::TIMESTAMP_NTZ)"))
java.sql.Timestamp t = java.sql.Timestamp.valueOf("2019-09-23 10:10:10.0");
for (int i = 0; i < 22; i++)
ps.setTimestamp(1, t);
ps.addBatch();
ps.executeBatch();
try (Statement statement = con.createStatement())
try (ResultSet resultSet = statement.executeQuery("select * from Test_TSNTZ "))
while (resultSet.next())
System.out.println(resultSet.getTimestamp(1));
【问题讨论】:
表格类型是TIMESTAMPNTZ
是不是打错字了?似乎应该是 'TIMESTAMP_NTZ' 。
如果您存储 NTZ 和 LTZ,那么您提出问题的方式似乎也很奇怪,“同时具有两种类型的时间戳”,您如何知道服务器中的哪个是哪个?我们经常在数据库中以 UTC 格式存储所有内容,因此在工作时不会出现跳跃间隙或混乱,只需了解您希望在 UI 中呈现的方式(什么 TZ)即可。所以看起来好坏参半
【参考方案1】:
如我所见,JDBC 连接器(不确定它是否特定于 Snowflake)如果变量被包围在函数或强制转换运算符。
作为一种解决方法,您可以将时间戳值作为字符串发送。 Snowflake 会将其转换为列类型:
try (Connection con = getConnection())
con.createStatement().execute("create or replace table Test_TSNTZ(t1 TIMESTAMP_NTZ, t2 TIMESTAMP_LTZ)");
try (PreparedStatement ps = con.prepareStatement("insert into Test_TSNTZ values ( ?, ? )"))
java.sql.Timestamp t = java.sql.Timestamp.valueOf("2019-09-23 10:10:10.0");
for (int i = 0; i < 22; i++)
ps.setString(1, t.toString());
ps.setString(2, t.toString());
ps.addBatch();
ps.executeBatch();
try (Statement statement = con.createStatement())
try (ResultSet resultSet = statement.executeQuery("select * from Test_TSNTZ "))
while (resultSet.next())
System.out.println(resultSet.getTimestamp(1) + "," + resultSet.getTimestamp(2) );
【讨论】:
感谢 Gokhan Atil 分享解决方法。这里有什么特别需要注意的吗?我的意思是我们是否需要将时间戳转换为任何特定格式或时区,然后与 setString 一起使用?它确实看起来像一个缺陷,如果不是那么寻找解决这个用例的方法。 在我的测试中,它不需要输入特定的格式。 Java 时间戳使用与 Snowflake 兼容的格式。无论如何,Snowflake 都会尝试自动检测时间戳的格式。以上是关于使用“?::TIMESTAMP_NTZ”在查询中指定类型时,Snowflake JDBC 批量插入失败并显示“绑定变量?未设置”的主要内容,如果未能解决你的问题,请参考以下文章
Snowflake SQL 错误 - 函数“-”的参数类型无效:(TIMESTAMP_NTZ(9), TIMESTAMP_NTZ(9))
Oracle数据库时间戳(6)转换为雪花timestamp_ntz时抛出错误