当处理大型表(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两边的一个子句,查询似乎启动好了。当然,查询在非分区表中正常工作。
非常感谢任何帮助或指示。
答案 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')