我们使用JDBC驱动连接到Snowflake并执行插入。当使用TIME数据类型时,我们在插入中使用setTime提供时间值为10:10:10,当使用getTime检索时,我们得到02:10:10。
文档中说--TIME内部存储的是 "挂钟 "时间,所有对TIME值的操作都是在不考虑任何时区的情况下进行的。
为什么要进行这种转换?如何确保我们拿回我们插入的东西?
示例程序 -
try (Connection con = getConnection()) {
try (PreparedStatement ps = con.prepareStatement("insert into Test_Time values (?)")) {
ps.setTime('10:10:10');
ps.executeUpdate();
}
try (Statement statement = con.createStatement()) {
try (ResultSet resultSet = statement.executeQuery("select * from Test_Time ")) {
while (resultSet.next()) {
System.out.println(resultSet.getTime(1));
}
}
}
}
我们都试过了
ps.setTime(Time.valueOf('10:10:10'))
ps.setTime('10:10:10')
当从WEB门户的工作表中尝试类似的方法时,我们看到插入的值是相同的10:10:10。Web门户能够显示正确的预期结果,所以想知道在我的情况下是否有任何基本的缺失?
先谢谢你的帮助。
更新--围绕这个问题做了更多测试--发现 "setTime(int idx, Time t) "和 "setTime(int idx, Time t, Calendar c) "之间没有区别。如果你已经知道你的数据的时区,那么就没有办法提供自定义时区。
从我所看到的搜索(例如,在这里 这里)这似乎是你使用的驱动程序的问题,而不是数据库的问题。我也看到了和你不同的结果--在我的脚本中,我插入了 10:10:10
并回到 10:10:10
但当我看到雪花表时,它显示的是 09:10:10
. 这是因为我住在伦敦,目前是北京时间(GMT+1),所以我的驱动程序在插入雪花之前,正在进行从本地时区到GMT的转换(当我的驱动程序插入到雪花时,我的驱动程序正在进行转换)。ps.setTime
运行时),以及从数据库中检索时(当 results.getTime
是运行)。)
这里的例子是scala,但代码基本相同。
val ps: PreparedStatement = connection.get.prepareStatement("insert overwrite into test_db.public.test_table values (?)")
val insertedTime: Time = Time.valueOf("10:10:10")
println(s"Inserting ${insertedTime} into table")
ps.setTime(1, insertedTime)
ps.executeUpdate()
val results: ResultSet = connection.get.createStatement().executeQuery("select time_col from test_db.public.test_table")
while(results.next) {
val returnedTime = results.getTime(1)
println(s"Time returned: ${returnedTime}")
}
上面的脚本打印出来:
Inserting 10:10:10 into table
Time returned: 10:10:10
在Snowflake中,时间是:
+----------+
| time_col |
+----------+
| 09:10:10 |
+----------+
为了解决这个问题,你可以将全局时区设置为GMT,然后运行同样的脚本。下面是同样的例子,将TimeZone改为GMT。
TimeZone.setDefault(TimeZone.getTimeZone("GMT+00:00")) // <----- ** New bit **
val ps: PreparedStatement = connection.get.prepareStatement("insert overwrite into test_db.public.test_table values (?)")
val insertedTime: Time = Time.valueOf("10:10:10")
println(s"Inserting ${insertedTime} into table")
ps.setTime(1, insertedTime)
ps.executeUpdate()
val results: ResultSet = connection.get.createStatement().executeQuery("select time_col from test_db.public.test_table")
while(results.next) {
val returnedTime = results.getTime(1)
println(s"Time returned: ${returnedTime}")
}
现在脚本打印出来了(一样)。
Inserting 10:10:10 into table
Time returned: 10:10:10
而在Snowflake中,时间现在显示的是你所期望的。
+----------+
| time_col |
+----------+
| 10:10:10 |
+----------+
转换是由Java完成的。如果你使用绑定一个字符串变量而不是时间变量,你会看到它和预期的一样。
CREATE TABLE test_time ( t TIME );
当我们运行下面的Java代码块时,它将插入 "10:10:10 "到表中。
try (Connection con = getConnection()) {
try (PreparedStatement ps = con.prepareStatement("insert into Test_Time values (?)")) {
ps.setString(1, "10:10:10" );
ps.executeUpdate();
}
try (Statement statement = con.createStatement()) {
try (ResultSet resultSet = statement.executeQuery("select * from Test_Time ")) {
while (resultSet.next()) {
System.out.println(resultSet.getString(1));
System.out.println(resultSet.getTime(1));
}
}
}
}
你会看到下面的输出
10:10:10
02:10:10
第一个是以字符串形式读取时间,第二个是使用Time对象,所以它被转换为你的时区。如果你在Web用户界面上查询该表,你会看到它将返回预期的值。
SELECT * FROM test_time;
+----------+
| T |
+----------+
| 10:10:10 |
+----------+
至少对我来说是有效的 :)