【问题标题】:Oracle: Difference between DATE and TIMESTAMP(0)Oracle:日期和时间戳之间的差异(0)
【发布时间】:2021-01-23 13:09:36
【问题描述】:

Oracle 中的 DATE 和 TIMESTAMP(0) 之间有什么区别(如果有)?这两种数据类型都占用 6 个字节,并且包含带时间的日期,但没有小数秒和时区。

TIMESTAMP 是在 DATE 大约 20 年后添加到 Oracle 中的,以符合 ANSI 标准。 TIMESTAMP 或 TIMESTAMP(6) 可以保存小数秒,所以它和 DATE 不同,但是 TIMESTAMP(0) 和 DATE 有什么区别吗?

【问题讨论】:

标签: oracle


【解决方案1】:

一个是DATE 数据类型,一个是TIMESTAMP 数据类型。

它们都占用 7 个字节(世纪、世纪、月、日、小时、分钟和秒)。

DATE 在显示时将被 NLS_DATE_FORMAT 会话参数隐式格式化。

TIMESTAMP 在显示时将被 NLS_TIMESTAMP_FORMAT 会话参数隐式格式化。

例如:

CREATE TABLE table_name (
  dt DATE,
  ts TIMESTAMP(0)
);

INSERT INTO table_name ( dt, ts ) VALUES ( SYSDATE, SYSTIMESTAMP );

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS.FF6';

然后:

SELECT dt,
       DUMP( dt ),
       ts,
       DUMP( ts )
FROM   table_name;

输出:

DT |转储(DT) | TS |转储(TS) :----------------- | :------------------------------------------------ | :------------------------- | :------------------------------------------------ 2020-10-08T14:21:35 | Typ=12 Len=7:120,120,10,8,15,22,36 | 2020-10-08T14:21:36.000000 | Typ=180 Len=7: 120,120,10,8,15,22,37

需要TIMESTAMP 输入的函数不会执行从DATETIMESTAMP 的隐式CAST

所以:

SELECT FROM_TZ( dt, 'UTC' ) FROM table_name;
SELECT FROM_TZ( CAST( dt AS TIMESTAMP(0) ), 'UTC' ) FROM table_name;
SELECT FROM_TZ( ts, 'UTC' ) FROM table_name;

第一条语句引发ORA-00932: inconsistent datatypes: expected TIMESTAMP got DATE 异常,但第二条和第三条有效。

正如@WernfriedDomscheit 在 cmets 中所提到的,DATETIMESTAMP 数据类型之间的算术也不同。例如:

SELECT dt - dt,
       ( dt - dt ) DAY TO SECOND,
       ts - ts
FROM   table_name

输出:

DT-DT | (DT-DT)DAYTOSECOND | TS-TS ----: | :----------------- | :----------------- 0 | +00 00:00:00.000000 | +000000000 00:00:00

最上面的表达式是DATE - DATE,结果是以天为单位的差值(表示为NUMBER 数据类型)。但是,底部表达式是TIMESTAMP - TIMESTAMP,结果是INTERVAL DAY TO SECOND 数据类型。可以通过 DATE 减法输出 INTERVAL DAY TO SECOND 数据类型,但如中间示例所示,您需要明确声明这是您需要的输出。

除了DATETIMESTAMP 也有区别。例如:

SELECT dt + 1,
       dt + INTERVAL '1' DAY,
       ts + 1,
       ts + INTERVAL '1' DAY
FROM   table_name

输出:

DT+1 | DT+INTERVAL'1'DAY | TS+1 | TS+INTERVAL'1'DAY :----------------- | :----------------- | :----------------- | :------------- 2020-10-09T19:52:21 | 2020-10-09T19:52:21 | 2020-10-09T19:52:22 | 2020-10-09T19:52:22.000000

将数字或INTERVAL 添加到DATETIMESTAMP 在语法上都是正确的(但可能与预期不同)。如果您看一下,您会看到在日期上添加数字或间隔的输出在两种情况下都会给出相同的输出。但是,将数字添加到时间戳与将间隔添加到时间戳相比,输出之间存在差异;这是因为您只能将数字添加到日期值,并且通过将数字添加到时间戳,然后 Oracle 执行了从时间戳到日期的隐式转换,因此:

SELECT ts + 1 FROM table_name

正在有效执行:

SELECT CAST(ts AS DATE) + 1 FROM table_name

因此,如果您想使用 TIMESTAMP 数据类型执行算术运算,请使用 INTERVAL 数据类型而不是数字。

db小提琴here

【讨论】:

    猜你喜欢
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 2023-02-12
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多