Snowflake JDBC时间数据类型值转换为UTC。

问题描述 投票:0回答:1

我们使用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) "之间没有区别。如果你已经知道你的数据的时区,那么就没有办法提供自定义时区。

snowflake-cloud-data-platform
1个回答
1
投票

从我所看到的搜索(例如,在这里 这里)这似乎是你使用的驱动程序的问题,而不是数据库的问题。我也看到了和你不同的结果--在我的脚本中,我插入了 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 |
+----------+

2
投票

转换是由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 |
+----------+

至少对我来说是有效的 :)

© www.soinside.com 2019 - 2024. All rights reserved.