我四处搜索,令人惊讶的是找不到 Oracle JDBC 的答案。这个密切相关的问题有 PostgreSQL 和 MySQL 的答案。
基本上,如果我在两个不同的时区有两台应用服务器将时间戳写入一个 Oracle 数据库,会发生什么情况?谢谢。
编辑:我应该补充一点,当我进行查询时,JDBC 发送到数据库的值似乎在我的本地时区。
我整理了一些测试 JDBC 代码来弄清楚到底发生了什么。结果很有趣。Oracle 具有三种密切相关的数据类型:TIMESTAMP
、TIMESTAMP WITH TIME ZONE
和TIMESTAMP WITH LOCAL TIME ZONE
. 我采用完全相同的代码,并从两个不同的盒子运行它,一个在“America/New_York”时区,一个在 UTC 上运行。两者都命中同一个数据库,以 UTC 运行。我使用的是 Oracle 11.2.0.2.0 驱动程序。
TIMESTAMP
列设置为执行 Java 代码的机器上的本地时间。未执行时区转换。TIMESTAMP WITH TIME ZONE
列将时间转换为 JDBC 客户端所在的任何时区。TIMESTAMP WITH LOCAL TIME ZONE
列还将时间转换为 JDBC 客户端所在的时区。这篇较旧的文章表明,TIMESTAMP WITH TIME ZONE
如果您想做诸如索引或分区之类的事情,那几乎没用。但是,它似乎TIMESTAMP WITH LOCAL TIME ZONE
可能非常有用。(不确定如果更改服务器的时区会发生什么,但它似乎对 JDBC 客户端的本地时区很智能)。我没有机会使用这些数据类型测试索引行为等。
如果您想在您的环境中重现我的测试,请在下面粘贴我的示例类。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.Date;
// create table x_tst_ts_tab(
// os_name varchar(256)
// ts timestamp,
// ts_with_tz timestamp with time zone,
// ts_with_local_tz timestamp with local time zone
// )
class TSTest {
public static final void main(String[] argv) throws Exception {
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection(
"your_connection_string",
"your_user_name",
"your_password");
try {
// Insert some data
Date nowDate = new Date();
Timestamp nowTimestamp = new Timestamp(nowDate.getTime());
PreparedStatement insertStmt = conn.prepareStatement(
"INSERT INTO x_tst_ts_tab"
+ " (os_name, ts, ts_with_tz, ts_with_local_tz)"
+ " VALUES (?, ?, ?, ?)");
try {
insertStmt.setString(1, System.getProperty("os.name"));
insertStmt.setTimestamp(2, nowTimestamp);
insertStmt.setTimestamp(3, nowTimestamp);
insertStmt.setTimestamp(4, nowTimestamp);
insertStmt.executeUpdate();
} finally {
try {
insertStmt.close();
} catch (Throwable t) {
// do nothing
}
}
System.out.println("os_name, ts, ts_with_tz, ts_with_local_tz");
// Read back everything in the DB
PreparedStatement selectStmt = conn.prepareStatement(
"SELECT os_name, ts, ts_with_tz, ts_with_local_tz"
+ " FROM dom_fraud_beacon.x_tst_ts_tab");
ResultSet result = null;
try {
result = selectStmt.executeQuery();
while (result.next()) {
System.out.println(
String.format("%s,%s,%s,%s",
result.getString(1),
result.getTimestamp(2).toString(),
result.getTimestamp(3).toString(),
result.getTimestamp(4).toString()
));
}
} finally {
try {
result.close();
} catch (Throwable t) {
// do nothing
} finally {
try {
selectStmt.close();
} catch (Throwable t) {
// do nothing
}
}
}
} finally {
try {
conn.close();
} catch (Throwable t) {
// do nothing
}
}
}
}