使用以下查询,将引发Oracle异常。 但是,我不明白为什么。任何人都能解释一下吗?
select visit_id, to_date(response, 'DD/MM/YYYY') as convertedDate from
(
select *
from dat_results_ext
where item_name = 'CALLBACKDATE'
)
where to_date(response, 'DD/MM/YYYY') > sysdate
我理解这个例外意味着它试图转换'响应'字段,但它符合非数字。问题是它应该带回的行具有正确格式的所有内容。
'response'字段是一个varchar字段,但是带有'item_name ='CALLBACKDATE'子句的所有行都是正确的格式。
有什么想法吗?
答案 0 :(得分:2)
优化器可以在尝试查找最佳执行计划之前重写您的查询。在您的情况下,由于您没有阻止优化器执行此操作的提示,因此可能会unnest your subquery并将您的查询重写为:
SELECT *
FROM dat_results_ext
WHERE item_name = 'CALLBACKDATE'
AND to_date(response, 'DD/MM/YYYY') > sysdate
您无法控制WHERE子句中语句的评估顺序,因此Oracle可能首先在不可转换为日期的行上评估to_date
函数,因此出错。 / p>
我看到两种方法可以强制Oracle按您想要的顺序评估语句:
使用rownum。 Rownum将实现子查询,防止Oracle将其与外部查询合并:
SELECT visit_id, to_date(response, 'DD/MM/YYYY') AS convertedDate
FROM (SELECT r.*,
rownum /* will materialize the subquery */
FROM dat_results_ext r
WHERE item_name = 'CALLBACKDATE')
WHERE to_date(response, 'DD/MM/YYYY') > sysdate
SELECT visit_id, to_date(response, 'DD/MM/YYYY') AS convertedDate
FROM (SELECT /*+ NO_MERGE */ *
FROM dat_results_ext
WHERE item_name = 'CALLBACKDATE')
WHERE to_date(response, 'DD/MM/YYYY') > sysdate
答案 1 :(得分:0)
必须先评估TO_DATE子句,然后才能确定WHERE子句的真实性。如果您有在TO_DATE函数中无法评估的响应值,您将看到错误。
答案 2 :(得分:0)
准确地说,这是因为response
的某些值与DD/MM/YYYY
的格式掩码不匹配。例如,如果您的会话设置为DD-MON-YY
的默认日期格式,请执行以下操作,您将收到错误消息: -
select to_date('17/SEP/2012','DD/MM/YYYY') from dual;
ERROR:
ORA-01858: a non-numeric character was found where a numeric was expected
由于您在月份字段中传递了一个字符,而Oracle需要一个数字。