【问题标题】:Strange Oracle Timestamp Behaviour奇怪的 Oracle 时间戳行为
【发布时间】: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


【解决方案1】:

似乎 Oracle 在查找适合您的过滤器日期的分区时使用了日期舍入,并且 12 月 16 日之后的高价值有效性检查正在被舍入到 10000 年之后。

当您通过添加时区组件更改过滤器的数据类型时,查询会起作用,因为您强制转换列值,这会阻止使用分区范围;指定 GMT 会改变计划:

----------------------------------------------------------------------------------------------------------                                                                                              
| Id  | Operation                 | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |                                                                                              
----------------------------------------------------------------------------------------------------------                                                                                              
|   0 | SELECT STATEMENT          |              |     1 |    13 |   120   (2)| 00:00:02 |       |       |                                                                                              
|   1 |  SORT AGGREGATE           |              |     1 |    13 |            |          |       |       |                                                                                              
|   2 |   PARTITION RANGE ITERATOR|              |   112K|  1430K|   120   (2)| 00:00:02 |     1 |     3 |                                                                                              
|*  3 |    TABLE ACCESS FULL      | TRADE_DEAL_F |   112K|  1430K|   120   (2)| 00:00:02 |     1 |     3 |                                                                                              
----------------------------------------------------------------------------------------------------------                                                                                              


PLAN_TABLE_OUTPUT                                                                                                                                                                                      
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):                                                                                                                                                     
---------------------------------------------------                                                                                                                                                     

   3 - filter("AUDIT_FROM_TS"<TIMESTAMP' 9999-12-15 00:00:00.000000000')                                                                                                                                

-----------------------------------------------------------------------------------------------------                                                                                                   
| Id  | Operation            | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |                                                                                                   
-----------------------------------------------------------------------------------------------------                                                                                                   
|   0 | SELECT STATEMENT     |              |     1 |    13 |   124   (5)| 00:00:02 |       |       |                                                                                                   
|   1 |  SORT AGGREGATE      |              |     1 |    13 |            |          |       |       |                                                                                                   
|   2 |   PARTITION RANGE ALL|              |   112K|  1430K|   124   (5)| 00:00:02 |     1 |1048575|                                                                                                   
|*  3 |    TABLE ACCESS FULL | TRADE_DEAL_F |   112K|  1430K|   124   (5)| 00:00:02 |     1 |1048575|                                                                                                   
-----------------------------------------------------------------------------------------------------                                                                                                   


PLAN_TABLE_OUTPUT                                                                                                                                                                                      
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):                                                                                                                                                     
---------------------------------------------------                                                                                                                                                     

   3 - filter(SYS_EXTRACT_UTC(INTERNAL_FUNCTION("AUDIT_FROM_TS"))<TIMESTAMP' 9999-12-15                                                                                                                 
              00:00:00.000000000')                                                                                                                                                                      

隐含的SYS_EXTRACT_UTC 导致它使用PARTITION RANGE ALL,如果你 使用那个高过滤器也没关系(尽管它有点多余);但如果您也从低值搜索,可能会产生更大的影响。

但是,如果您有间隔分区,转换日期为一个月的第一天,这里似乎就是这种情况,那么无论如何您都不能在 9999 年 12 月插入任何具有 audit_from_ts 值的记录,因为这需要一个分区10000-01-01 的高值,这不是一个合法的日期。这是提到in the documentation

例如,如果您创建具有每月间隔的间隔分区表,并且转换点位于 2010 年 1 月 1 日,则 2010 年 1 月间隔的下限为 2010 年 1 月 1 日。2010 年 7 月间隔的下限是 2010 年 7 月 1 日,无论之前是否创建了 2010 年 6 月分区。但是请注意,使用分区的上限或下限超出存储范围的日期会导致错误。例如,TO_DATE('9999-12-01', 'YYYY-MM-DD') 导致上限为 10000-01-01,如果 10000 超出合法范围,则该上限将无法存储。

因此,如果您无法在该月获得值,那么无论您使用 9999-12-31、9999-12-15 还是 9999-12-01 作为过滤器,这在逻辑上都没有任何区别。 (您可以通过将转换日期设为每月 18 日来使查询与 9999-12-31 一起工作,但这会有点奇怪,而且您仍然无法在 9999-12-17 之后插入记录)。

Oracle 不认为这是一个错误。您可以在 My Oracle Support 文档 1507993.1 中了解更多信息。

【讨论】:

  • 老实说,这似乎是一个错误。非常感谢您的回答。这对您有很大帮助!
猜你喜欢
  • 2020-01-30
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 2019-12-19
  • 2022-01-19
  • 2011-11-20
  • 2014-11-30
  • 2014-01-05
相关资源
最近更新 更多