PostgreSQL 9.4-сравнение нулевых значений
При нормальных условиях сравнение значения NULL
с любым другим значением приводит к другому значению NULL
.
SELECT NULL = NULL;
Возвращает NULL
Это справедливо (в основном) при сравнении произвольных строк, как описано в документации, 9.23.5. Сравнение Конструктора Строк :
SELECT ROW(1, NULL, 'baz text') = ROW(1, NULL, 'baz text');
Возвращает NULL
Однако при сравнении хорошо определенных составных типов значения
NULL
рассматриваются как равные.
CREATE TYPE test_type AS (
foo INTEGER,
bar BIGINT,
baz TEXT
);
SELECT (1, NULL, 'baz text')::test_type = (1, NULL, 'baz text')::test_type;
Возвращает TRUE
Я хотел бы использовать это поведение для реализации некоторых бизнес-правил и хочу убедиться, что это безопасно.
- согласуется ли это с какой-либо спецификацией SQL?
- вероятно ли , что это изменится в будущем?
2 ответа:
Я нашел это в официальной документации : [...] В других контекстах, где сравниваются два значения составного типа, два значения нулевого поля считаются равными, а нулевое значение считается большим, чем ненулевое. Это необходимо для того, чтобы иметь согласованное поведение сортировки и индексирования для составных типов.. Я думаю, что это решает ваш вопрос.
Иллюстрация (извините, я не могу сделать это в комментарии, нужно форматирование):
CREATE TYPE test_type AS ( foo INTEGER , bar BIGINT , baz TEXT ); -- plain table with three fields CREATE TABLE test_table0 ( foo INTEGER , bar BIGINT , baz TEXT ); -- the same, but with a composite type CREATE TABLE test_table1 ( tt test_type ); INSERT INTO test_table0 (foo,bar,baz) VALUES (1, NULL, 'baz text'); INSERT INTO test_table1 (tt) VALUES( (1, NULL, 'baz text')::test_type) ; -- union needs a "whole row" -compare SELECT * FROM test_table0 UNION SELECT * FROM test_table0 ; -- union needs a "whole row" -compare -- and type needs a whole "composite" compare SELECT * FROM test_table1 UNION SELECT * FROM test_table1 ;
Результат:
CREATE TYPE CREATE TABLE CREATE TABLE INSERT 0 1 INSERT 0 1 foo | bar | baz -----+-----+---------- 1 | | baz text (1 row) tt ----------------- (1,,"baz text") (1 row)
- Примечание: сравниваемые объекты (экземпляры типов и кортежи) не являются нулевыми, только некоторые из их элементов.
- я действительно думаю, что это и есть предполагаемое поведение
- ИМХО это близко к проблеме с допуском нулевых элементов в составных ключах, (смотрите разглагольствования Криса дэйта об этом)
- вероятно, другой поведение привело бы к еще более странным артефактам