Мне кажется, что c.value
содержит значения, которые не являются датами. Просто никто из них не в первых двадцати рядах. Таким образом, запрос успешно выполняется, когда TO_DATE () применяется во внешнем запросе, потому что преобразование применяется только к первым двадцати значениям. Однако применение преобразования во внутреннем запросе означает попытку преобразования всех строк, включая те, которые содержат значения, которые не являются датами.
Это одна из ловушек при использовании структуры базы данных, которая хранит данные в общих строковых столбцах вместо использования соответствующих типов данных.
Что с этим делать? Разумеется, вы можете изменить модель данных, чтобы даты содержались в столбцах, определенных с использованием типа данных DATE, но я подозреваю, что это может потребовать больше усилий, чем вы ищете. Альтернативой может быть использование клуджа, подобного этому
create or replace function is_a_date
(p_str in varchar2
, p_mask in varchar2 := 'MM/DD/YYYY HH24:MI:SS')
return date
is
return_value date;
begin
begin
return_value := to_date(p_str, p_mask);
exception
when others then
return_value := null;
end;
return return_value;
end;
/
Это берет строку и пытается преобразовать ее в дату, используя маску формата. Если это дата в соответствующем формате, она возвращает дату, в противном случае она возвращает ноль:
SQL> select is_a_date('01/01/2000 23:56:07') from dual
2 /
IS_A_DATE
---------
01-JAN-00
SQL> select is_a_date('APC is not a date') from dual
2 /
IS_A_DATE
---------
SQL>