在此选择中,显示4条记录,其中3个空值表示不相关,而一个空值表示相关。
结果:
当我在WHERE pc.contype <> 'p'
中添加约束时,仅所有记录,而不仅仅是'p'。
结果:
我无法理解发生了什么,这是我放手的规则吗?
答案 0 :(得分:1)
所以这里发生的是pg_indexes有4行与您的WHERE条件匹配。当您左联接时,即使没有联接,您也会保留所有行。在您的情况下,只有一行加入pg_constraint。
当LEFT JOIN连接行失败时,它将用NULL填充所有可能的列。这意味着在您的情况下,未连接pg_constraint的3行现在对于pg_constraint指定的所有列都为NULL。
最后,谈到____ <>'p'的比较时,您缺少SQL处理NULL值的规则。 NULL被视为缺少值,而不是您可以比较的值。任何使用标量比较的尝试都将失败。
您可以通过更改为WHERE (pc.contype IS NULL OR pc.contype <> 'p')
答案 1 :(得分:1)
NULL不等于(或不等于)任何东西,包括NULL本身。忽略您使用的是LEFT JOIN并假设contype
可为空:条件WHERE contype <> 'p'
不会仅因为NULL <> 'p'
是未知的(不是真的)而与NULL不匹配!
您将编写以下内容以获取右表中不匹配的行:
WHERE contype <> 'p' OR contype IS NULL
答案 2 :(得分:1)
您要寻找的是NULL
安全比较。 Postgres为此支持ANSI / ISO标准功能,所以我建议:
WHERE contype IS DISTINCT FROM 'p'
这在documentation中有解释。
答案 3 :(得分:0)
您使用的是left join,因此即使pg_indexes
对于相同的键没有任何对应的数据,也会总是返回pg_constraints
数据。这就是第一次查询中发生的事情。在第二个查询中,您添加了一个检查以仅返回pg_constraints
值不为p
的数据,这一次NULL
的值也将被检查,并且由于检查失败而不会显示。如果此检查位于join子句中,则它仍将显示NULL
值,但它位于where子句中,并过滤整个结果集。左联接是外部联接,它将始终从联接左边的表返回所有数据,即使联接右边的相同值不存在,您也要记住这一点。
答案 4 :(得分:0)
pc.contype <> 'p'
子句中的附加条件WHERE
有效地击败了外部联接,并将其转换为内部联接。将该谓词放在ON
子句中。
您可能想要类似的东西:
select
pc.contype
from pg_indexes pi
left join pg_constraint pc on pi.indexname = pc.conname
and pc.contype <> 'p'
where pi.tablename = 'mytable'