Почему функция ORACLE TO_DATE не выдает ошибку ORA-01841 в условии OR, когда пропускаются пробелы? - PullRequest
0 голосов
/ 19 декабря 2018
SQL> select to_date('    ','YYYYMMDD') from dual;
ERROR at line 1:
ORA-01841: (full) year must be between -4713 and +9999, not be 0

SQL> select * from dual where to_date('    ','YYYYMMDD') = '19960512' or 1 = 2;
ERROR at line 1:
ORA-01841: (full) year must be between -4713 and +9999, not be 0

SQL> select * from dual where to_date('    ','YYYYMMDD') = '19960512' or 1 = 1;
Success.

В первых двух утверждениях мы передаем пробелы в функцию TO_DATE, которая выдает ожидаемую ошибку.Но

Теперь в третьем утверждении мы передаем пробелы функции оракула TO_DATE, которая не разрешена.Но все же он выполняется успешно.

Почему?

В реальном коде я мог бы передавать пробелы из переменной, и часть ИЛИ может быть или не быть истинной.

Может кто-нибудь объяснить мне это поведение и как обработать, чтобы получить ошибку?

PS - Я на Oracle 12g EE

Ответы [ 3 ]

0 голосов
/ 19 декабря 2018

Другой ответ не касался той части вашего вопроса, где вы все еще хотели получить ошибку

Я рекомендую вам выполнить анализ даты отдельно.Если это хранимая процедура, не помещайте запрос так, как вы это сделали здесь, создайте переменную даты, используйте to_date, чтобы присвоить ей значение даты (произойдет сбой, если пользователь предоставит пробелы), затем используйте переменную датыв запросе.Таким образом, если даны неверные данные, у оракула все еще есть шанс подавиться им.

В качестве альтернативы заставьте вашу процедуру хранения принимать параметр типа даты, а не строку, чтобы заставить вызывающую программу предоставить что-то разумное и непротиворечивую дату

0 голосов
/ 19 декабря 2018

Вы можете повторить преобразование в пределах ветви or, которая, очевидно, немного запутана:

select * from dual
where to_date('    ','YYYYMMDD') = '19960512'
or (1 = 1 and to_date('    ','YYYYMMDD') != '19960512');

Error report -
ORA-01841: (full) year must be between -4713 and +9999, and not be 0

Или, если единственный сценарий с недействительной датой, о котором вам нужно беспокоиться, это пробелы, вы можете сделатьчто-то еще, чтобы эта ветвь оценивалась как ложная в этом случае:

select * from dual
where to_date('    ','YYYYMMDD') = '19960512'
or (1 = 1 and trim('    ') is not null);

строка из базы данных извлекается и передается в TO_DATE в запросе

подразумевает, что выхранение дат в виде строк в вашей базе данных, , что не очень хорошая идея ;поэтому, если у вас есть пробелы, у вас может быть что угодно, и вам придется иметь дело и с другими потенциальными ошибками, которые не подхватит подход is not null.

И ни один из этих запросов не выдаст ошибку спередана пустая строка (т. е. null), но тогда и ваши первые два исходных запроса не будут;все они просто не найдут данных.


Конечно, '19960512' не дата, поэтому вы делаете здесь дополнительные неявные преобразования;было бы безопаснее пропустить это через to_date() или использовать литерал даты, если это действительно фиксированное значение:

where to_date('    ','YYYYMMDD') = date '1996-05-12'
0 голосов
/ 19 декабря 2018

Oracle использует здесь логику короткого замыкания.Поскольку известно, что 1=1 соответствует действительности, Oracle оптимизирует оценку другого условия.Поскольку он никогда не оценивается, тот факт, что вы передаете ему недопустимые аргументы, несущественен.

...