检查Postgres复合字段是否为空/空

cod*_*ama 23 sql postgresql null composite

使用postgres复合类型,您基本上可以构建一个字段,其结构被定义为另一个表.我有一个名为"person"类型的"收件人"的复合字段.在我的特定方案中,此收件人字段通常为空.检查复合字段是否为空的正确方法是什么.我试过了:

select * from bla where recipient is not null
select * from bla where recipient is null
select * from bla where recipient = null
select * from bla where recipient != null
Run Code Online (Sandbox Code Playgroud)

在所有这些情况下,它都不会返回任何内容.那么如何正确检查复合值是否为空?

UPDATE

经过一些阅读后,看起来这是我的问题:

人们可能认为!(x IS NULL) = x IS NOT NULL在所有情况下都是如此.但是有一个例外 - 复合类型.当复合值的NULL一个字段是另一个字段时NOT NULL,则两个运算符的结果都为假.IS NULL是真的,只有当所有的领域都是NULL.IS NOT NULL是真的,只有当所有的领域都是NOT NULL.对于介于两者之间的任何情况,两个运算符都返回false.

我确实有一些空字段,有些字段不是.我希望如果复合字段中的任何项不为null,则该字段将被视为非NULL,而不是当所有项都不为空时.除了检查每个字段之外还有什么方法吗?

Mur*_*nik 20

IS NULL并且也IS NOT NULL适用于复杂类型,所以这两个应该是合适的:

select * from bla where recipient is not null
select * from bla where recipient is null
Run Code Online (Sandbox Code Playgroud)


Erw*_*ter 14

要捕获不是复合值(行/记录)的所有字段都为NULL的情况:

SELECT *
FROM   bla
WHERE  NOT (recipient IS NULL);
Run Code Online (Sandbox Code Playgroud)

<row-type> is NULLTRUE所有字段都返回时返回NULL.
<row-type> is NOT NULLTRUE所有字段都返回时返回NOT NULL.

括号是可选的.无论如何,运算符优先级对我们有利.

测试行/记录为NULL

展示各种选择:

CREATE TEMP TABLE recipient (r text, i int);  -- to register the row type

SELECT recipient
     , recipient IS NULL         AS all_null
     , recipient IS NOT NULL     AS all_notnull
     , NOT recipient IS NULL     AS some_notnull
     , NOT recipient IS NOT NULL AS some_null
FROM (
   VALUES
    (('foo', 1   )::recipient)
  , ((NULL , 2   )::recipient)
  , ((NULL , NULL)::recipient)
   ) AS tbl(recipient);
Run Code Online (Sandbox Code Playgroud)

结果:

 recipient | all_null | all_notnull | some_notnull | some_null
-----------+----------+-------------+--------------+-----------
 (foo,1)   | f        | t           | t            | f
 (,2)      | f        | f           | t            | t
 (,)       | t        | f           | f            | t
Run Code Online (Sandbox Code Playgroud)

SQL小提琴.

有关: