2013-07-01 1 views
0

Я использую Postgres 9.1. Следующий запрос не работает должным образом. Coalesce должен вернуть первое непустое значение . Однако этот запрос возвращает null (1?) Вместо даты (2).Coalesce and Case-When с To_Date не работает должным образом (ошибка Postgres?)

select COALESCE(
    TO_DATE('','yyyymmdd'), --(1) 
    TO_DATE('20130201','yyyymmdd') --(2) 
    ); 

--(1) this evaluates independently to null 
--(2) this evaluates independently to the date, 
-- and therefore is the first non-null value 

Что я делаю неправильно? Любое обходное решение?

Редактировать: Это не может иметь ничего общего с Coalesce. Я пробовал некоторые эксперименты с конструкциями Case When; получается, Postgres имеет этот большой уродливый баг , где он рассматривает TO_DATE('','yyyymmdd') как не пуст, хотя выбор его возвращает null.

[PS: Забастовка выше, чтобы не вводить в заблуждение. Postgres не имеет ошибки, но не обрабатывает пустые строки как null. См ответ.]

+0

В 9.0, 'to_date ('' , 'yyyymmdd') '' '0001-01-01 BC'. Почему вы думаете, что 'to_date ('', 'yyyymmdd')' должно быть NULL? [Документация для 'to_date'] (http://www.postgresql.org/docs/current/interactive/functions-formatting.html) нигде не упоминает NULL. Я не могу найти никакого упоминания о том, что делает 'to_date', если строка не упоминает шаблон, но я только сделал беглый обзор. У меня нет стандартной копии, поэтому я не знаю, что она должна сказать. –

+0

Кроме того, стоит отметить, что 'to_date ('00000000', 'yyyymmdd')' также '0001-01-01 BC', поэтому, возможно, * missing * означает * zero *. –

+0

Не имеет смысла для 'to_date ('', ...)' быть 'NULL'; вы даете ему ненулевой ввод. Если что-то должно быть ошибкой. «Выбор его» создает ненулевой (но все еще ужасный) результат '0001-01-01 BC'. Здесь нет никаких признаков ошибки, и из вашего сообщения неясно, что вы думаете, что это предполагаемая ошибка, поскольку вы не определяете точное поведение, которое вы ожидаете. Вы ожидаете, что PostgreSQL будет обрабатывать пустую строку и null как одно и то же? –

ответ

4
SELECT TO_DATE('','yyyymmdd'); 

не имеет значение, так как вы NULL передавая пустую строку вместо NULL в качестве аргумента TO_DATE()

Это будет успешно вычисляться NULL

SELECT TO_DATE(NULL,'yyyymmdd'); 

Если вы ожидайте пустую строку и хотите обработать ее как NULL. Вы можете использовать NULLIF()

SELECT TO_DATE(NULLIF(dt, ''),'yyyymmdd') 
    FROM 
(
    SELECT CAST('' AS VARCHAR(32)) dt 
) q 

Это сказанное ваш пример кода, который оценивает (1), как NULL

SELECT COALESCE(
    TO_DATE(NULLIF('', ''),'yyyymmdd'),  --(1) 
    TO_DATE(NULLIF('20130201',''),'yyyymmdd') --(2) 
); 

и возвращает

 
|      COALESCE | 
----------------------------------- 
| February, 01 2013 00:00:00+0000 | 

Вот SQLFiddle демо

+0

Но вы можете оправдать 'TO_DATE ('', 'yyyymmdd')' быть '0001-01-01 BC' или' to_date (null, 'yyyymmdd') 'быть' NULL'? Эмпирические результаты заставляют мою внутреннюю базу данных сжиматься. –

+0

Ну 'to_date (null, 'yyyymmdd)' '' NULL' IMHO является абсолютно нормальным и последовательным в любых РСУБД, о которых я могу думать. Теперь 'STR_TO_DATE ('', '% Y% m% d')' в Mysql также укажет нулевую дату, которая будет '0000-00-00'. Oracle обрабатывает пустую строку как NULL, поэтому 'SELECT TO_DATE ('') FROM dual' просто дает вам NULL. – peterm

+2

Да, 'to_date' с' null' должно быть 'null', это разумно и разумно. Я отчасти ужасаюсь 'to_date ('', ...)' возвращающ что-нибыдь за исключением ошибки; Я могу только предположить, что это было принято решение о совместимости с другими базами данных. –

Смежные вопросы