有一种奇怪的行为让我发疯。
我在旧的SQL Server 2000数据库中有一个用户表和一个权限表。 这个数据库很乱,很多表没有PK,表之间也没有关系......但我无法解决它(老实说,我不认为这与我遇到的问题有关)。
Users:
IDRecord -> PK money
-- other fields
Permissions:
IDRecord -> money (is not a PK)
IDUser -> money (refers to Users.IDRecord WITHOUT FK)
Function -> varchar
-- other fields
我想在未经许可的情况下获取用户的用户ID。
我的第一个方法是写一些东西:
select distinct IDRecord
from Users
where IDRecord not in (
select IDUser from Permissions
)
这不会让我返回任何行。
但是我知道有没有权限的用户,所以我写了第二个查询:
select distinct U.IDRecord
from Users U
left join Permissions P
on P.IDUser = U.IDRecord
where P.IDRecord is null
正确地返回没有权限的用户。
那么,问题在哪里?
为什么第一个不起作用?
答案 0 :(得分:4)
这是预期的行为
这是预期的,因为SQL有three-valued logic
换句话说:对于没有权限的用户,子查询没有返回结果(NULL)
在这些情况下,您的WHERE
条件不满足,因为值永远不能等于也不等于NULL。
替代品:
1)使用LEFT JOIN
(正如您所做的那样)或
2)使用NOT EXISTS
,例如:
SELECT DISTINCT IDRecord
FROM Users u
WHERE NOT EXISTS (
SELECT 1
FROM Permissions p
WHERE p.IDUser = u.IDRecord
);
编辑:如果您不小心,3VL如何咬你的更多细节:
如果您执行此类操作,可能会出现反直觉的结果......
...
WHERE a_column <> 'some value';
突然,a_column
为NULL的行会从结果中消失。
要让他们回来,你可以这样做:
...
WHERE (a_column <> 'some value' OR a_column IS NULL);