我编写了一个查询,用通用表检查表的完整性。查询是以下
SELECT * FROM Universal
WHERE UNIVERSAL.TYPE=MYTYPE
AND Universal.CLASS=MYCLASS
AND Universal.ID NOT IN (SELECT Mytable.ID FROM Mytable)
如您所见,我在查找完整性之前过滤了通用表,两者都在同一个查询中。我现在发现当我删除NOT IN部分时,查询运行正常,但是当我包含它时,我得不到任何结果。这个查询有什么问题?如何使用其他形式编写,例如使用连接或其他东西?
答案 0 :(得分:2)
SELECT * FROM Universal
WHERE UNIVERSAL.TYPE=MYTYPE
AND Universal.CLASS=MYCLASS
AND Universal.ID NOT IN (SELECT Mytable.ID FROM Mytable
WHERE Mytable.ID IS NOT NULL)
空而不是......!
SELECT
返回WHERE
子句为TRUE
的行,且不返回FALSE
行。
也不返回UNKNOWN
行(即NULL
行。)这通常不是问题,但是当涉及到NOT IN
时,许多程序员会感到惊讶。
假设您有一张汽车牌桌,并且您想要返回列表(或子查询)中找不到的颜色的汽车:
select * from cars where color not in ('red', 'blue')
很容易理解,所有车辆都会返回红色和蓝色。
但是如果颜色列表使用未知颜色(NULL
)进行扩展,那么它将是:
select * from cars where color not in ('red', 'blue', NULL)
现在WHERE
子句不知道是否例如黄色车是否在列表中,肯定不是红色或蓝色,但我们无法判断它是不是那种未知的NULL
颜色...... I.e。 WHERE
子句变为未知,并且不返回任何行!
这里程序员可以通过在子查询中指定IS NOT NULL
来避免使用未知颜色。 (或者转换为NOT EXISTS
,这是“空安全”。)
答案 1 :(得分:2)
所以你想要选择不在Mytable中的Universal的所有内容吗? 使用LEFT JOIN将选择来自和Unive的所有内容,并且只选择Mytable中与Universal相匹配的行。因此,如果Mytable.ID为null,那么Universal的那一行在Mytable中没有匹配的行:
SELECT * FROM Universal
LEFT JOIN Universal.ID = Mytable.ID
WHERE UNIVERSAL.TYPE=MYTYPE
AND Universal.CLASS=MYCLASS
AND Mytable.ID IS NULL;
答案 2 :(得分:2)
我使用您的架构和查询创建了一个SQL小提琴。它运行正常。 Demo 1
但是当我向Mytable添加NULL值时,它不再起作用。这是一个例子: Demo 2
如果您采用该示例并从Mytable中过滤掉空值,则可以再次正常工作。 Demo 3
答案 3 :(得分:0)
SELECT * FROM Universal U
WHERE U.TYPE=MYTYPE
AND U.CLASS=MYCLASS
AND NOT EXISTS (SELECT ID FROM Mytable WHERE ID = U.ID)