您能帮助清除 ORACLE 时间戳与本地时区的混淆吗?

Jas*_*Krs 1 oracle

以下是ORACLE的说明 TIMESTAMP WITH LOCAL TIME ZONE

...存储在数据库中的数据被规范化为数据库时区,时区偏移量不作为列数据的一部分存储。当用户检索数据时,Oracle在用户的本地会话时区返回数据。

什么是存储在数据库中的数据进行归一化到数据库时区手段?标准化...如何?

如果它是规范化的,为什么不相应地返回服务器的时区而不是用户的本地会话时区......它是如何“会话”而不是“服务器”?

Bal*_*app 7

标准化意味着不存储时区信息。存储此类数据时,时间戳值会自动调整为与数据库服务器处于同一时区。检索此类数据时,时间戳值会自动调整为与客户端处于同一时区。

例如,我模拟我的客户在不同的时区:

$ export TZ=America/Los_Angeles
$ sqlplus user/password@orcl
Run Code Online (Sandbox Code Playgroud)

创建一个表来存储时间戳值:

SQL> create table t1 (t timestamp with local time zone);

Table created.
Run Code Online (Sandbox Code Playgroud)

现在请注意我的本地(客户端)时间 ( current_timestamp) 与服务器时间 ( systimestamp)有何不同:

SQL> select current_timestamp, systimestamp from dual;

CURRENT_TIMESTAMP                   SYSTIMESTAMP
----------------------------------- -----------------------------------
29-DEC-16 06.36.09.364628 AM -08:00 29-DEC-16 03.36.09.364623 PM +01:00
Run Code Online (Sandbox Code Playgroud)

现在我插入我的本地时间:

SQL> insert into t1 (t) values (current_timestamp);

1 row created.

SQL> commit;

Commit complete.

SQL> select t from t1;

T
---------------------------------------------------------------------------
29-DEC-16 06.36.32.100571 AM
Run Code Online (Sandbox Code Playgroud)

正是我所期望的。但如果我检查一下真实内容:

SQL> select dump(t) from t1;

DUMP(T)
----------------------------------------------------
Typ=231 Len=11: 120,116,12,29,16,37,33,5,254,151,120
Run Code Online (Sandbox Code Playgroud)

TIMESTAMP 存储为:

  • 第一个字节:年份的前两位数字:20 + 100 = 120
  • 第二个字节:年份的最后两位数字:16 + 100 = 116
  • 第三个字节:月:12
  • 第四个字节:天:29
  • 第 5 个字节:小时:15 + 1 = 16
  • 第 6 个字节:分钟:36 + 1 = 37
  • 第 7 个字节:第二个:32 + 1 = 33
  • 第 8-11 个字节:秒的小数部分

时区信息将在第 12 和第 13 字节中,但不使用此数据类型存储。

所以实际存储的数据是2016-12-29 15:36:32:...,因为我的数据库在CET时区。

如果我假装在另一个不同的时区,我的查询将返回调整到该时区的时间戳:

$ export TZ=Asia/Hong_Kong
$ sqlplus user/password@orcl


SQL> select t from t1;

T
---------------------------------------------------------------------------
29-DEC-16 10.36.32.100571 PM
Run Code Online (Sandbox Code Playgroud)