一个是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 输入的函数不会执行从DATE 到TIMESTAMP 的隐式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 中所提到的,DATE 和 TIMESTAMP 数据类型之间的算术也不同。例如:
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 数据类型,但如中间示例所示,您需要明确声明这是您需要的输出。
除了DATE 或TIMESTAMP 也有区别。例如:
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 添加到DATE 和TIMESTAMP 在语法上都是正确的(但可能与预期不同)。如果您看一下,您会看到在日期上添加数字或间隔的输出在两种情况下都会给出相同的输出。但是,将数字添加到时间戳与将间隔添加到时间戳相比,输出之间存在差异;这是因为您只能将数字添加到日期值,并且通过将数字添加到时间戳,然后 Oracle 执行了从时间戳到日期的隐式转换,因此:
SELECT ts + 1 FROM table_name
正在有效执行:
SELECT CAST(ts AS DATE) + 1 FROM table_name
因此,如果您想使用 TIMESTAMP 数据类型执行算术运算,请使用 INTERVAL 数据类型而不是数字。
db小提琴here