我们有一个表格,其中日期以YYYYMMDD的格式存储为VARCHAR2(它是我们无法控制的遗留数据表!)。我们对表只有SELECT权限(不可编写过程/函数)。
需要从日期为>的表格中选择所有行SYSDATE。
我们对正确的格式和其他检查应用正则表达式检查,以确保该日在给定月份有效。这一切都很棒!我们的内联视图选择确保只选择具有有效日期字符串的记录。
但是,当我们申请条件检查> sysdate作为外部子句 - 即使内联视图选择确保没有选择此类记录,我们也会得到给定月份错误的无效日期。
在应用内联视图条件之前,查询执行似乎正在应用外部子句中的条件。感谢对行为的任何评论;并且,我们如何确保只有在满足内联条件后才能应用来自外部的条件?
数据和使用的查询:
CREATE TABLE TEST_DATA_TABLE
(
DATESTRING VARCHAR2(20 BYTE)
);
插入包含值的3行:
19960322 --Valid Date in past
19831131 --Invalid Date 11/31
20180224 --Valid Date > SYSDATE
有效数据选择: (其中第1条确保格式,第2条确保月份的有效日期):
SELECT datestring AS i_dob
FROM test_data_table
WHERE REGEXP_LIKE (TRIM (datestring),
'(19|20)\d\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])')
AND TRIM (datestring) <=
TO_CHAR (
LAST_DAY (
TO_DATE (SUBSTR (TRIM (datestring), 1, 6) || '01',
'YYYYMMDD')),
'YYYYMMDD')
上面的查询工作正常并返回有效日期字符串
的有效行选择具有日期字符串&gt;的记录SYSDATE,上面的数据是内联使用的,我们应用条件&gt; SYSDATE如下。
SELECT i_dob
FROM (
SELECT datestring AS i_dob
FROM test_data_table
WHERE REGEXP_LIKE (TRIM (datestring),
'(19|20)\d\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])')
AND TRIM (datestring) <=
TO_CHAR (
LAST_DAY (
TO_DATE (SUBSTR (TRIM (datestring), 1, 6) || '01',
'YYYYMMDD')),
'YYYYMMDD')
) X
WHERE TO_DATE (X.I_DOB, 'YYYYMMDD') > SYSDATE
它开始抛出错误:ORA-01839: date not valid for month specified
看起来在检查所有内联视图条件之前应用条件。
答案 0 :(得分:0)
你可以通过在外部查询之前通过向其添加一个额外的rownum列来操作内联视图来解决这个问题(rownum列的存在意味着Oracle需要为它之前应用的子查询计算该列。可以进一步过滤它。
因此,您的查询将变为:
SELECT i_dob
FROM (
SELECT datestring AS i_dob,
rownum rn
FROM test_data_table
WHERE REGEXP_LIKE (TRIM (datestring),
'(19|20)\d\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])')
AND TRIM (datestring) <=
TO_CHAR (
LAST_DAY (
TO_DATE (SUBSTR (TRIM (datestring), 1, 6) || '01',
'YYYYMMDD')),
'YYYYMMDD')
) X
WHERE TO_DATE (X.I_DOB, 'YYYYMMDD') > SYSDATE;
我会在你的查询中添加一条评论来解释这个专栏的存在,否则将来某些开发人员可能会认为“呃?这什么都不做;我会删除它!”。
(另外值得注意的是在12.2中,他们添加/修改了允许easier data validation的函数,当你到达12.2时这会简化你的查询!)