Oracle TIMESTAMP字段中的实际日期是什么?

时间:2015-05-21 11:09:40

标签: sql oracle

我有一个数据类型为TIMESTAMP的字段(DD-MON-RR HH.MI.SSXFF AM是格式)。当我在SQL开发人员中运行select语句时,此字段显示'04-NOV-08 12.00.00.000000000 AM'作为结果,我认为08是2008年,但是当我在我的java代码中调试时,此字段显示值'Sun Nov 04 00:00:00 ICT 8 '这意味着年份是8.你能告诉我哪个是正确值吗?

1 个答案:

答案 0 :(得分:1)

您的默认NLS_TIMESTAMP_FORMAT(您可以更改as shown here,虽然您不应该真正依赖它)会为您提供两位数的年份代表。

出于显示目的,YY和RR date format models之间没有区别。您的查询显示年份为08,但这可能代表任何世纪的第8年。

正如@DanBracuk建议你可以通过指定四位数年份格式掩码来查看全年,to_char(value, 'YYYY-MM-DD');那给了你0008-11-04。因此,存储在时间戳中的值实际上是在第8年,而不是2008年,Java正在向您显示正确的值。 (如果您将数据作为日期时间而不是字符串传递,那么您会期望;但是您没有表明这一点。)

由于您可能实际上并不想在表格中使用第8年的数据,因此您会遇到数据问题。您可能能够通过简单地为每个值添加2000年来纠正您的数据,但这假设它们都显示从第一个世纪开始的一年,并且其余日期是正确的。

你还需要弄清楚数据是如何到达那里的,以及它是否仍在用错误的世纪创建。最简单的解释可能是从具有四位数年度NLS设置的会话插入期间提供的两位数年份。这正是您不应该依赖NLS_DATE_FORMAT,NLS_TIMESTAMP_FORMAT等的原因,因为编写代码的人通常无法控制运行它的人的会话。

您可以通过此演示了解2位数年份和4位数字掩码会发生什么。这将插入使用to_dateto_timestamp以及RR,RRRR,YY和YYYY格式掩码转换的相同字符串值的数据。

create table t42 (id number, ts timestamp);
insert into t42 (id, ts) values (1, to_date('04-NOV-08', 'DD-MON-RR'));
insert into t42 (id, ts) values (2, to_timestamp('04-NOV-08', 'DD-MON-RR'));
insert into t42 (id, ts) values (3, to_date('04-NOV-08', 'DD-MON-RRRR'));
insert into t42 (id, ts) values (4, to_timestamp('04-NOV-08', 'DD-MON-RRRR'));
insert into t42 (id, ts) values (5, to_date('04-NOV-08', 'DD-MON-YY'));
insert into t42 (id, ts) values (6, to_timestamp('04-NOV-08', 'DD-MON-YY'));
insert into t42 (id, ts) values (7, to_date('04-NOV-08', 'DD-MON-YYYY'));
insert into t42 (id, ts) values (8, to_timestamp('04-NOV-08', 'DD-MON-YYYY'));

    select id, ts, to_char(ts, 'YYYY-MM-DD') as full_year from t42;

        ID TS                           FULL_YEAR
---------- ---------------------------- ----------
         1 04-NOV-08 00.00.00.000000000 2008-11-04
         2 04-NOV-08 00.00.00.000000000 2008-11-04
         3 04-NOV-08 00.00.00.000000000 2008-11-04
         4 04-NOV-08 00.00.00.000000000 2008-11-04
         5 04-NOV-08 00.00.00.000000000 2008-11-04
         6 04-NOV-08 00.00.00.000000000 2008-11-04
         7 04-NOV-08 00.00.00.000000000 0008-11-04
         8 04-NOV-08 00.00.00.000000000 0008-11-04

使用我的默认时间戳模型的字符串表示显示所有值都相同,所有年份都显示为08,如您所见。但是,使用YYYY格式掩码插入的值 - 正确地 - 被解释为0008而不是2008。

您还可以看到完全依赖于NLS设置的内容:

alter session set nls_timestamp_format = 'DD-MON-YY HH24:MI:SS.FF3';

insert into t42 (id, ts) values (9, '04-NOV-08');

alter session set nls_timestamp_format = 'DD-MON-YYYY HH24:MI:SS.FF3';

insert into t42 (id, ts) values (10, '04-NOV-08');

select id, ts, to_char(ts, 'YYYY-MM-DD') as full_year from t42 where id > 8;

        ID TS                       FULL_YEAR
---------- ------------------------ ----------
         9 04-NOV-2008 00:00:00.000 2008-11-04
        10 04-NOV-0008 00:00:00.000 0008-11-04

运行了相同的代码,但最终得到了两个非常不同的值。

除了即席查询之外,或许,不要依赖NLS设置。您不应该对其他用户的会话设置做任何假设。如果您有要转换为日期或时间戳的字符串值,请始终显式调用to_dateto_timestamp并指定正确的格式掩码。如果可能,您应该在字符串值中使用4位数年份。您也可以使用日期/时间戳文字,具体取决于字符串的呈现方式。