我们在表格中有一列如下:
预测| TIME_BASIS
01.12.2014 |日常
01.12.2014 14:14 |盘中
201435 |每周
请注意,我们使用欧洲日期格式(DD.MM.YYYY)。
现在,当我想将每日字符串转换为日期时,我看到一些奇怪的行为:
select day_id from
(
select to_date(forecast_time, 'DD.MM.YYYY') day_id
from wfm_forecasts_new
where time_basis = 'daily'
)
where day_id = '07.07.2014'
结果: ORA-01830:日期格式图片在转换整个输入字符串之前结束
01830. 00000 - “日期格式图片在转换整个输入字符串之前结束”
*原因:
*操作:的
另一方面,我按照以下方式执行查询:
select day_id from
(
select to_date(forecast_time, 'DD.MM.YYYY') day_id
from wfm_forecasts_new a1
where a1.time_basis = 'daily'
)
group by day_id
having day_id = '07.07.2014'
它返回我预期的结果:
DAY_ID
2014年7月7日的
有没有人对这种行为有合理的解释?我们需要有可能使用where子句。
非常感谢您的帮助 最好的祝福, 克里斯
答案 0 :(得分:0)
问题是Oracle选择评估谓词的顺序。它可以选择在内部重写查询以使其更有效。
从您的观点来看,似乎很明显,在两个查询中,内部选择只会查看并尝试转换daily
个记录;但实际上它可能会选择将to_date
函数应用于每条记录,然后才应用daily
过滤器。
这意味着它会尝试以to_date('01.12.2014 14:14', 'DD.MM.YYYY')
为例,这就是产生ORA-01830错误的原因。您可以查看两个查询的执行计划,以查看差异,尤其是“访问”和“过滤器”信息。
它在两个查询中表现不同,这并不罕见,因为您已经改变了解析器可能选择处理数据集的方式。这取决于您的数据和统计数据;当我使用几条记录运行原始查询时,它们都会收到错误。
您可以添加一个提示来停止谓词推送,或者您可以在内部查询中添加格式检查,例如:
select day_id from
(
select to_date(forecast_time, 'DD.MM.YYYY') day_id
from wfm_forecasts_new
where time_basis = 'daily'
and regexp_like(forecast_time, '^\d{1,2}\.\d{1,2}\.\d{4}$')
)
where day_id = '07.07.2014';
你应该真正做其中一个,虽然你目前在外部where
子句中有一个隐式转换:
where day_id = to_date('07.07.2014', 'DD.MM.YYYY');
where day_id = date '2014-07-07';
由于第二个查询也可能以同样的方式出错,因此您需要使用类似的方法。
这可能是一个非常简化的例子,但如果这真的是你正在做的事情,我不确定你为什么不只是过滤字符串值:
select to_date(forecast_time, 'DD.MM.YYYY') day_id
from wfm_forecasts_new
where time_basis = 'daily'
and forecast_time = '07.07.2014';
...除非您希望在正则表达式方法处理的日期和月份编号中允许可选的前导零。