使用postgres composite types,您基本上可以构建一个字段,其结构被定义为另一个表。我有一个名为“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
在所有这些情况下,它都不会返回任何内容。那么如何正确检查复合值是否为空?
更新
经过多次阅读后,看起来这是我的问题:
有人可能会认为
!(x IS NULL) = x IS NOT NULL
在所有情况下都是正确的。但是有一个例外 - 复合类型。当复合值的一个字段为NULL
而另一个字段为NOT NULL
时,则两个运算符的结果均为false。仅当所有字段均为IS NULL
时,NULL
才为真。仅当所有字段均为IS NOT NULL
时,NOT NULL
才为真。对于介于两者之间的任何情况,两个运算符都返回false。
我确实有一些空字段,有些字段不是。我希望如果复合字段中的任何项不为null,则该字段将被视为非NULL,而不是当所有项都不为空时。除了检查每个字段之外,还有其他方法吗?
答案 0 :(得分:16)
IS NULL
和IS NOT NULL
也适用于复杂类型,所以这两个应该是合适的:
select * from bla where recipient is not null
select * from bla where recipient is null
答案 1 :(得分:13)
要捕获并非复合值(行/记录)的所有字段为NULL的情况:
SELECT *
FROM bla
WHERE NOT (recipient IS NULL);
如果所有字段均为<row-type> is NULL
,则 TRUE
仅返回NULL
。
如果所有字段均为<row-type> is NOT NULL
,则TRUE
仅返回NOT 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);
结果:
recipient | all_null | all_notnull | some_notnull | some_null
-----------+----------+-------------+--------------+-----------
(foo,1) | f | t | t | f
(,2) | f | f | t | t
(,) | t | f | f | t
相关: