Oracle 12c 按范围间隔月份进行分区 ORA-01841
Oracle 12c PARTITION BY RANGE INTERVAL MONTH ORA-01841
在处理巨大 tables(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: (full) year must be between -4713 and +9999, and not be 0
01841. 00000 - "(full) year must be between -4713 and +9999, and not be 0
*Cause: Illegal year entered
*Action: Input year in the specified range
"interesting" 的事情是,如果您删除 OR 两边的一个子句,查询似乎可以正常启动。当然,查询在非分区 table.
中正常工作
非常感谢任何帮助或指点。
这看起来像错误,可能是 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 所建议的那样,undocumentedno_expand_table
提示似乎确实有帮助。
尝试使用 >=
select * from date_test WHERE
TO_DATE('20061201','YYYYMMDD') OR JOURNAL_DATE >=
TO_DATE('20061231','YYYYMMDD') ) ;( JOURNAL_DATE <
或在
之间使用
where JOURNAL_DATE between to_date('20061201','YYYYMMDD') and
TO_DATE('20061231','YYYYMMDD')
在处理巨大 tables(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: (full) year must be between -4713 and +9999, and not be 0
01841. 00000 - "(full) year must be between -4713 and +9999, and not be 0
*Cause: Illegal year entered
*Action: Input year in the specified range
"interesting" 的事情是,如果您删除 OR 两边的一个子句,查询似乎可以正常启动。当然,查询在非分区 table.
中正常工作非常感谢任何帮助或指点。
这看起来像错误,可能是 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 所建议的那样,undocumentedno_expand_table
提示似乎确实有帮助。
尝试使用 >=
select * from date_test WHERE TO_DATE('20061201','YYYYMMDD') OR JOURNAL_DATE >= TO_DATE('20061231','YYYYMMDD') ) ;( JOURNAL_DATE <
或在
之间使用where JOURNAL_DATE between to_date('20061201','YYYYMMDD') and TO_DATE('20061231','YYYYMMDD')