table 的 DATE 数据类型列反映了哪个时区?
Which time zone does the table's column of DATE data type reflect?
在 Oracle 数据库中我有这个 table(列 col
的数据类型是 DATE
):
列
2021-02-2623:14:24
问题:在我的例子中,假设随着时间的推移数据库设置没有改变,DATE
的table列是哪个时区数据类型反映?
- UTC 或
- Europe/Helsinki?
下面我提供当前的数据库设置。
- 数据库时区
SELECT DBTIMEZONE FROM DUAL;
|DBTIMEZONE |
|============|
|+00:00 |
- 会话时区
SELECT SESSIONTIMEZONE FROM DUAL;
|SESSIONTIMEZONE|
|===============|
|Europe/Helsinki|
SELECT CURRENT_DATE FROM DUAL;
|CURRENT_DATE |
|===================|
|2021-07-18 15:05:32|
- 数据库服务器操作系统的时区
SELECT SYSDATE FROM DUAL;
|SYSDATE |
|===================|
|2021-07-18 15:05:32|
SELECT SYSTIMESTAMP FROM DUAL;
|SYSTIMESTAMP |
|==============================|
|2021-07-18 15:05:32.984 +03:00|
如果数据是 DATE 类型,则它根本不反映任何时区。这只是一个日期和时间,时间精确到秒。 SYSDATE 只是从主机服务器 OS 获取日期和时间,因此就时间部分反映任何时区而言,它将是主机 OS.
的时间部分
列未定义时区。
你可以这样做:
CREATE TABLE table_name (col DATE);
ALTER SESSION SET TIME_ZONE = 'UTC';
INSERT INTO table_name (col) VALUES (CURRENT_DATE);
ALTER SESSION SET TIME_ZONE = 'Europe/Helsinki';
INSERT INTO table_name (col) VALUES (CURRENT_DATE);
ALTER SESSION SET TIME_ZONE = 'America/New_York';
INSERT INTO table_name (col) VALUES (CURRENT_DATE);
然后:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
SELECT * FROM table_name;
输出:
COL
2021-07-18 21:06:05
2021-07-19 00:06:05
2021-07-18 17:06:05
db<>fiddle here
这些值都是由同一用户在同一会话中使用相同的 SQL 语句在同一秒内插入的;但是,DATE
值的时区不一致,因为会话设置在每个语句之间发生了更改;所以你不能依赖 DATE
有任何特定时区。
如果您想知道您的数据所在的时区,请检查您存储数据的应用程序:
- 是否一直在使用
SYSDATE
?那么该列的时区就是数据库系统的时区。
- 应用程序是否指定时区?然后数据将具有应用程序指定的时区。
- 是否从外部来源获取数据?然后检查该外部来源。
- 它是否从用户那里获取数据?那你就没有保障了。
在 Oracle 数据库中我有这个 table(列 col
的数据类型是 DATE
):
列 |
---|
2021-02-2623:14:24 |
问题:在我的例子中,假设随着时间的推移数据库设置没有改变,DATE
的table列是哪个时区数据类型反映?
- UTC 或
- Europe/Helsinki?
下面我提供当前的数据库设置。
- 数据库时区
SELECT DBTIMEZONE FROM DUAL;
|DBTIMEZONE |
|============|
|+00:00 |
- 会话时区
SELECT SESSIONTIMEZONE FROM DUAL;
|SESSIONTIMEZONE|
|===============|
|Europe/Helsinki|
SELECT CURRENT_DATE FROM DUAL;
|CURRENT_DATE |
|===================|
|2021-07-18 15:05:32|
- 数据库服务器操作系统的时区
SELECT SYSDATE FROM DUAL;
|SYSDATE |
|===================|
|2021-07-18 15:05:32|
SELECT SYSTIMESTAMP FROM DUAL;
|SYSTIMESTAMP |
|==============================|
|2021-07-18 15:05:32.984 +03:00|
如果数据是 DATE 类型,则它根本不反映任何时区。这只是一个日期和时间,时间精确到秒。 SYSDATE 只是从主机服务器 OS 获取日期和时间,因此就时间部分反映任何时区而言,它将是主机 OS.
的时间部分列未定义时区。
你可以这样做:
CREATE TABLE table_name (col DATE);
ALTER SESSION SET TIME_ZONE = 'UTC';
INSERT INTO table_name (col) VALUES (CURRENT_DATE);
ALTER SESSION SET TIME_ZONE = 'Europe/Helsinki';
INSERT INTO table_name (col) VALUES (CURRENT_DATE);
ALTER SESSION SET TIME_ZONE = 'America/New_York';
INSERT INTO table_name (col) VALUES (CURRENT_DATE);
然后:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
SELECT * FROM table_name;
输出:
COL 2021-07-18 21:06:05 2021-07-19 00:06:05 2021-07-18 17:06:05
db<>fiddle here
这些值都是由同一用户在同一会话中使用相同的 SQL 语句在同一秒内插入的;但是,DATE
值的时区不一致,因为会话设置在每个语句之间发生了更改;所以你不能依赖 DATE
有任何特定时区。
如果您想知道您的数据所在的时区,请检查您存储数据的应用程序:
- 是否一直在使用
SYSDATE
?那么该列的时区就是数据库系统的时区。 - 应用程序是否指定时区?然后数据将具有应用程序指定的时区。
- 是否从外部来源获取数据?然后检查该外部来源。
- 它是否从用户那里获取数据?那你就没有保障了。