5

来自 Stack Overflow 的尊敬的 SQL 大师:

环境:甲骨文

我试图理解为什么我不能对包含字符串的表列进行 to_date 选择。注意下例中列名为 Value 的 tableZ 包含一堆字符串,其中一些是正确的格式,例如 6/20/2010 00:00:00。

表Z

| Value              |
| __________________ |
| 6/21/2010 00:00:00 |
| Somestring         |
| Some Other strings |
| 6/21/2010 00:00:00 |
| 6/22/2010 00:00:00 |

以下作品

SELECT To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
          FROM tableX a, tableY b, tableZ c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.other_id 
           AND b.id = c.new_id

这会返回类似的东西(这很好):

| somedate            |
| __________________  |
| 21.06.2010 00:00:00 |
| 21.06.2010 00:00:00 |
| 22.06.2010 00:00:00 |

以下不起作用

SELECT To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
          FROM properties$aud a, template_properties$aud b, consumable_properties$aud c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.property_id 
           AND b.id = c.template_property_id 
           AND To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') IS NOT NULL

回来了:

ORA-01861: 文字与格式字符串不匹配

我在这里想念什么?只是一个简短的说明:

 ...
AND b.id = c.template_property_id 
AND To_Date(c.Value, 'DD.MM.YYYY HH24:MI:SS') IS NOT NULL

也不行。

谢谢!!

目标是能够对 c.value 进行日期查询以选择日期范围。

4

4 回答 4

10

Oracle 评估 where 子句中的条件的顺序是不固定的。也就是说它可以选择在其他条件之前评估包含 TO_DATE 的条件,在这种情况下查询将失败。为防止这种情况,请在查询中添加 ordered_predicates 提示,但请注意,这可能需要额外的手动调整以提高性能。

SELECT /*+ ordered_predicates */
               To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
          FROM properties$aud a, 
               template_properties$aud b, 
               consumable_properties$aud c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.property_id 
           AND b.id = c.template_property_id 
           AND To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') IS NOT NULL

显然ordered_predicates从 10g 开始已弃用。在这种情况下,我认为您唯一的选择是以这样一种方式使用子查询,即优化器必须首先评估它(即它不能组合查询)。最简单的方法是放入rownum内部查询的 where 语句。

SELECT To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
  FROM (SELECT value 
          FROM properties$aud a, 
               template_properties$aud b, 
               consumable_properties$aud c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.property_id 
           AND b.id = c.template_property_id
           AND rownum > 0) 
 WHERE To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') IS NOT NULL
于 2010-06-23T20:20:34.070 回答
3

另一种技术是将转换嵌入到 CASE 中。例如

SELECT * FROM table
WHERE col_a = '1'
AND case when col_a = '1' then to_date(col_b,'DD/MM/YYYY') end = trunc(sysdate)

但是,当子句很复杂时,这会变得非常难看。

于 2010-06-24T00:28:05.063 回答
2
create or replace function to_date_or_null(v_str_date in varchar2
        , v_str_fmt in varchar2 default null) return date as
begin
    if v_str_fmt is null then
        return to_date(v_str_date);
    else
        return to_date(v_str_date, v_str_fmt);
    end if;
exception
    when others then
        return null;
end to_date_or_null;
/

测试:

SQL> select to_date_or_null('2000-01-01', 'YYYY-MM-DD') from dual -- Valid;

TO_DATE_OR_NULL('20
-------------------
2000-01-01 00:00:00

SQL> select to_date_or_null('Not a date at all') from dual -- Not Valid;

TO_DATE_OR_NULL('NO
-------------------


SQL> select to_date_or_null('2000-01-01') from dual -- Valid matches my NLS settings;

TO_DATE_OR_NULL('20
-------------------
2000-01-01 00:00:00

SQL> select to_date_or_null('01-Jan-00') from dual -- Does not match my NLS settings;

TO_DATE_OR_NULL('01
-------------------
于 2010-06-23T22:46:13.337 回答
0

你想检查 c.value 是否是一个有效的格式

AND To_Date(c.Value, 'DD.MM.YYYY HH24:MI:SS') IS NOT NULL

? 这不起作用,您将需要以其他方式执行检查。您可以使用正则表达式(我猜,暂时没有使用它们)。如果您的数据模型允许您辨别有问题的行,那就更好了。

于 2010-06-23T20:02:12.823 回答