Oracle 12c按范围区间划分ORA-01841

时间:2017-07-24 13:07:49

标签: oracle oracle12c

当处理大型表(2b +行)的概念的一些分区证明时,我们想出了一些奇怪的select语句行为:

create table date_test (
JOURNAL_ID VARCHAR2(10 BYTE) NOT NULL ENABLE, 
JOURNAL_DATE DATE NOT NULL ENABLE
)
PARTITION BY RANGE (JOURNAL_DATE) INTERVAL (NUMTOYMINTERVAL(1,'MONTH')) 
(
PARTITION P_20010101  VALUES LESS THAN (TO_DATE('20010101', 'YYYYMMDD'))
);

运行此查询时:

select * from date_test
 WHERE (
 JOURNAL_DATE < TO_DATE('20061201','YYYYMMDD')
 OR 
 JOURNAL_DATE > TO_DATE('20061231','YYYYMMDD')
 ) ;

我收到以下错误:

  

ORA-01841 :(完整)年份必须介于-4713和+9999之间,而不是0   01841. 00000 - “(完整)年份必须介于-4713和+9999之间,而不是0
  *原因:非法年份进入   *行动:在指定范围内输入年份

“有趣”的是,如果你删除OR两边的一个子句,查询似乎启动好了。当然,查询在非分区表中正常工作。

非常感谢任何帮助或指示。

2 个答案:

答案 0 :(得分:1)

这看起来像臭虫,可能是20961659或其亲属之一。您可以通过更改the optimizer_features_enable setting来解决这个问题,如果您不希望它更广泛地应用,您可以在查询中执行此操作:

select /*+ optimizer_features_enable('12.1.0.1') */ * from date_test
 WHERE (
 JOURNAL_DATE < TO_DATE('20061201','YYYYMMDD')
 OR 
 JOURNAL_DATE > TO_DATE('20061231','YYYYMMDD')
 ) ;

在12.1.0.2.170117中,我看到原始查询出现同样的错误;但有了这个提示它就能按预期工作。

当然要注意副作用,如果有疑问,您可以随时向Oracle支持部门提出服务请求。

Read more in the documentation,并在My Oracle Support中探索与此错误相关的条目。

在这种情况下,您似乎也可以通过将逻辑反转为使用and的包含日期范围来获得您想要的结果,并使用not否定该结果;但你需要阻止优化器将其更改回来 - 这可能会再次出现问题,但a no_query_transformation hint似乎可以解决问题:

select /*+ no_query_transformation */ * from date_test
 WHERE NOT (
 JOURNAL_DATE >= TO_DATE('20061201','YYYYMMDD')
 AND 
 JOURNAL_DATE <= TO_DATE('20061231','YYYYMMDD')
 ) ;

no_expand hint似乎没有帮助;虽然正如@WernfriedDomscheit建议的那样,未记录的 no_expand_table提示确实似乎有所帮助。

答案 1 :(得分:0)

尝试使用&gt; =

  

从date_test WHERE中选择*   TO_DATE('20061201','YYYYMMDD')或JOURNAL_DATE&gt; =   TO_DATE('20061231','YYYYMMDD'));(JOURNAL_DATE&lt;

或在

之间使用
  

其中JOURNAL_DATE介于to_date('20061201','YYYYMMDD')和   TO_DATE( '20061231', 'YYYYMMDD')