Литеральная строка не соответствует строке формата для Oracle SQL TO_DATE в строковом столбце

StackOverflow https://stackoverflow.com/questions/3105003

  •  29-09-2019
  •  | 
  •  

Вопрос

Уважаемый SQL Gurus из переполнения стека:

Окружающая среда: Оракул

Я пытаюсь понять, почему я не могу сделать выбор TO_DATE на столбце таблицы, который содержит строки. Примечание Tablez с столбцом значения имени в приведенном ниже примере содержит кучу строк, некоторые из которых являются правильным форматом, например, с 20.06.2010 00:00:00.

таблица

| 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: Literal не соответствует строке формата формата

Что мне здесь не хватает? Просто быстрое примечание:

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

тоже не работает.

Спасибо!!

Цель Чтобы иметь возможность выполнять дату между запросами на C.value, чтобы выбрать диапазоны дат.

Это было полезно?

Решение

Порядок, который Oracle оценивает условия, обнаруженные в пункте «Где не исправлен». То есть он может оценить условие, содержащее to_date перед другими критериями, и в этом случае запрос потерпит неудачу. Чтобы предотвратить это, добавьте намек на заказ на ваш запрос, но имейте в виду, что это может потребовать дополнительной ручной настройки для повышения производительности.

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 В заявлении о внутреннем запросе.

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

Другие советы

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
-------------------

Другая техника - это преобразование в случай. Например

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

Это становится очень уродливым быстро, когда положения сложны.

Вы хотите проверить, является ли C.value действительным форматом с

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

? Это не сработает, вам нужно будет выполнить чек другим способом. Вы можете использовать регулярное выражение (я думаю, не использовал их давно). Еще лучше, если ваша модель данных позволит вам различить рассматриваемые строки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top