Разница между нулевым составным типом и составным типом со всеми пустыми столбцами

Есть ли разница между нулевым значением и типом строки, где все столбцы равны нулю? Похоже, что запросы Postgres способны различать (отображая пустые столбцы, а не пустые), и я хочу знать, есть ли что-то, о чем я должен знать. например

CREATE TYPE node AS (
   rank integer
 , id integer
);

CREATE TABLE hierarchy (
   node node
);

INSERT INTO hierarchy (node) VALUES (null);
INSERT INTO hierarchy (node) VALUES ((null, null));

SELECT *, node IS NULL AS check_null FROM hierarchy;
 node | check_null
------+------------
      | t
 (,)  | t

1 ответ

Решение

Есть ли разница между нулевым значением и типом строки, где все столбцы равны нулю?

NULL:node все еще отличается от (null, null)::node:

SELECT null::node IS DISTINCT FROM (null, null)::node AS dist;
dist
----
t

Я согласен, что это сбивает с толку. И руководство может быть также заточено здесь:

Для ненулевых входов IS DISTINCT FROM такой же, как <> оператор. Однако, если оба входа имеют значение null, он возвращает false, а если только один вход имеет значение null, он возвращает true.

Оказывается, немного неверно перед лицом выше демо. Хотя есть подсказка ниже:

Если expression является строкой, то IS NULL Значение true, если само выражение строки равно нулю или когда все поля строки равны нулю.

Итак, у нас есть два разных случая, в которых значение строки равно нулю:

  1. Само выражение является нулевым.
  2. все поля строки равны нулю.

Следует отметить, что эти два случая все еще считаются различными по сравнению с IS DISTINCT FROM, Может быть, стоит сообщение об ошибке документации...

что-нибудь, о чем я должен знать?

Да. Где бы DISTINCT вступает в игру, оба варианта рассматриваются, ну, четко:

SELECT DISTINCT * FROM hierarchy;
 node1
------
 (,)  

(2 rows)

Обратите внимание на 2-ю невидимую строку, потому что psql отображает нулевые значения таким образом.

Чтобы остановить случай (,)?

Обращаясь к вашему комментарию:

CREATE TABLE hierarchy (
  node node CHECK (node IS DISTINCT FROM (null, null)::node)
);

Обратите внимание на две вещи:

  1. Явное приведение (null, null)::node является необходимым.
  2. Простые значения NULL все еще разрешены, только строка со всеми нулевыми значениями нарушает ограничение.
Другие вопросы по тегам