Конкатенация строк с нулем, кажется, сводит на нет всю строку - это то, что нужно в 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
Подробнее в Документация