Конкатенация строк с нулем, кажется, сводит на нет всю строку - это то, что нужно в Postgres?

В Postgres:

select 'test' || null  returns null

Я ожидал, что в противном случае он вернет "тест".

Это желаемое поведение? Кажется странным, что конкатенация строк с нулевым значением аннулирует всю строку...

Ссылаясь на pg docs: http://www.postgresql.org/docs/9.1/static/functions-string.html

"Примечание: перед PostgreSQL 8.3 эти функции будут молча принимать значения нескольких нестроковых типов данных из-за наличия неявных принуждений от этих типов данных к тексту. Эти принуждения были удалены, поскольку они часто вызывали неожиданное Однако оператор конкатенации строк (||) по-прежнему принимает нестроковый ввод, если хотя бы один вход имеет тип строки, как показано в таблице 9-6. В других случаях вставляйте явное принуждение к тексту если вам нужно дублировать предыдущее поведение."

Учитывая это, используя их пример функции concat string:

concat (str "any" [, str "any" [,...]]) text Конкатенация всех аргументов. Аргументы NULL игнорируются. concat ('abcde', 2, NULL, 22) → abcde222

Должен ли я просто привыкнуть к этому поведению с помощью '||' конкатенация или это что-то, что нужно исправить?

Ответ 1

Это не ошибка, и это не "странно".

Стандарт SQL требует выражения, которое включает null дает null. Это не ограничивается конкатенацией строк, это также относится к вычислениям, например: 42 * null возвращает null.

Это также относится к сравнениям: 42 > null дает null. Таким образом, сравнение не является ни истинным, ни ложным. Хотя на самом деле это имеет эффект "ложь", но больше, потому что это "не верно", а не ложно. Но отрицание такого выражения снова возвращает null, а не "истину".

Поскольку null является настолько особенным, единственный способ проверить, является ли что-то нулевым, - использовать оператор IS NULL или IS NOT NULL. x is null дает либо true, либо false, он никогда не дает null, поэтому выражения, использующие оператор IS NULL или IS NOT NULL, никогда не возвращают null - так что это исключение для моего высказывания выше (спасибо Jonathan за указание на это).


Другой - возможно, удивительный факт о значении null - это то, как они обрабатываются совокупными функциями. В то время как выражение 4 + 5 + null дает null, sum() по тем (столбцам) значениям будет давать 9, потому что агрегаты игнорируют значения null.

Учитывая следующую таблицу:

    col1
--------
       1
       2
       3 
     null

sum(col1) вернет 6, а avg(col1) вернет 2 (sum = 6, добавлено количество элементов: 3)

Ответ 2

Да, это желаемое поведение.

Вот пример, в котором это очень полезно. Скажем, у вас есть таблица лиц, в которой есть поля title, firstname, nameaffix и lastname. Чтобы создать полное имя, вы можете просто сделать это.

COALESCE(title || ' ', '') || firstname || COALESCE(' ' || nameaffix, '') || ' ' || lastname

Без этого странного поведения, которое вполне могло бы разместить места в правильных местах в зависимости от того, является ли поле нулевым или нет. Предполагая обязательное имя и фамилию, включается любая комбинация названия и имени.

Ответ 3

Цитата из документации

Объединить все аргументы. Аргументы NULL игнорируются.

Пример

concat('abcde', 2, NULL, 22) 

Возвращает

abcde222

Подробнее в Документация