我一直在写一些看起来像这样的查询:
SELECT
...
FROM table_a a
LEFT JOIN table_b b
ON b.id = a.id
LEFT JOIN table_c c
ON c.id = a.id
在这些查询中,只有一个连接可以成功。换句话说,来自的行与来自的行或来自的table_a
行匹配。table_b
table_c
在选择列表中,有一些基于连接成功的逻辑。我可以通过执行以下操作来测试它:
SELECT
CASE
WHEN b IS NULL THEN
-- do something
ELSE NULL
END
FROM table_a a
LEFT JOIN table_b b
ON b.id = a.id
LEFT JOIN table_c c
ON c.id = a.id
测试某行是否可用时,NULL
您可以在表达式中使用表别名IS NULL
,但它在表达式中无法按预期工作IS NOT NULL
。table_b
如果其中有不存在的列NULL
,则表达式table_b IS NOT NULL
将返回FALSE
。
但是,表达式将按预期NOT (table_b IS NULL)
返回。TRUE
为什么会这样?
这是一个悲伤的故事。
当 SQL 标准委员会定义
NULL
复合值的 -ness 时,他们一定是吃错药了。无论如何,他们裁定如果所有元素都是 ,则为复合,如果所有
IS NULL
元素都是NULL
,则为复合IS NOT NULL
NOT NULL
。换句话说,存在既不是
NULL
也不是 的复合材料NOT NULL
。PostgreSQL 实现了这一点,但
NOT NULL
在大多数其他方面都像对待复合材料一样对待复合材料。对此有过讨论,但面对标准的定义,没有人能提出一致的解决方案。这是一团糟,如果你想保持内心的平静,建议你不要想太多。
劳伦兹说的。
NOT (b IS NULL)
正如您发现的那样,按预期工作。但是在连接表达式中测试列会更容易混淆并且更快:该列是
NOT NULL
当(且仅当)找到匹配行时。有关的: