【发布时间】:2015-10-20 17:09:24
【问题描述】:
我被困住了。
Oracle 在处理时间戳时表现出奇怪的行为,让我解释一下:
我有一个带有主键和索引的简单表。 AUDIT_FROM_TS 是主键的一部分。它每月使用AUDIT_FROM_TS 进行分区。
相关的 DDL
CREATE TABLE "SDR"."TRADE_DEAL_F"(
...
"AUDIT_FROM_TS" TIMESTAMP (9) DEFAULT SYS_EXTRACT_UTC(SYSTIMESTAMP) NOT NULL ENABLE,
...
CONSTRAINT "PK_TRADE_DEAL" PRIMARY KEY ("TRADE_DEAL_ID", "VALID_FROM_DT", "AUDIT_FROM_TS")
...
PARTITION BY RANGE ("AUDIT_FROM_TS") INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
...
运行此查询时:
select count(*) from trade_deal_f where AUDIT_FROM_TS < timestamp '9999-12-31 00:00:00';
我明白了
ORA-01841:(完整)年份必须介于 -4713 和 +9999 之间,并且不能为 0 01841. 00000 - “(完整)年份必须介于 -4713 和 +9999 之间,并且不能为 0” *原因:非法输入年份 *Action:在指定范围内输入年份
但是这个很好用:
select count(*) from trade_deal_f where AUDIT_FROM_TS < timestamp '9999-12-15 00:00:00';
我做了一些调试,如果将日期增加到 9999 年 12 月 16 日,则会引发同样的错误。
现在进行更多调试...
SELECT DBTIMEZONE from dual;
返回+00:00
SELECT SESSIONTIMEZONE FROM dual;
返回Europe/London
有人可以帮忙吗?我不是 100% 确定这是时区问题,因为它会将日期偏移 2 周...
select count(*) from trade_deal_f where AUDIT_FROM_TS = timestamp '9999-12-31 00:00:00 Europe/London';
select count(*) from trade_deal_f where AUDIT_FROM_TS = timestamp '9999-12-31 00:00:00 GMT';
select count(*) from trade_deal_f where AUDIT_FROM_TS = timestamp '9999-12-31 00:00:00 UTC';
select count(*) from trade_deal_f where AUDIT_FROM_TS = timestamp '9999-12-31 00:00:00 +00:00';
所有这些似乎都是有效的......
【问题讨论】:
-
您可以尝试将 UTC 时区添加到时间戳文字中吗:
timestamp '9999-12-31 00:00:00 00:00' -
您好 dnoeth,感谢您的贡献...我添加了有效的查询(包括时区)。不幸的是,这并不能解决我的问题,我有很多以这种方式定义的表和写入它们的通用作业。这是唯一显示此行为的表....
-
AUDIT_FROM_TS 的数据类型是什么? (您已经给出了 VALID_FROM_DT 的数据类型,但这并不是您在查询中使用的数据类型)。您能否更新您的创建表语句以包含此列?
-
我的错,抱歉复制了错误的列...现在更新了,其他列也有同样的问题
-
解决这个问题,如果过渡日期从月初增加到第二个月,ORA-01841 直到 9999 年 12 月 17 日才会出现。因此,这似乎与分区范围有关,大概与该月底之后的一些内部计算有关。
标签: sql oracle timestamp oracle12c timestamp-with-timezone