SQL Server 2000奇怪的子查询问题
问题描述:
有一种奇怪的行为令我疯狂。SQL Server 2000奇怪的子查询问题
我有一个用户表和旧的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
我想在没有任何权限的情况下获取用户的用户标识。
我的第一种方法是写的东西为:
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
是正确返回用户没有权限。
那么,问题在哪里呢?
为什么第一个不起作用?
答
这是预期的行为。
这是因为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);
很奇怪的行为 – 2011-04-01 07:23:29
事实证明,如果列表中(无论是手动或子查询)中至少有一个NULL不是永远不返回TRUE。看起来像是按照设计。 – 2011-04-01 08:45:40
因此,作为Adam解决方案的替代方案,您可以修改子查询,如下所示:'从IDUser不为空的权限中选择IDUser。或者,也许是时候查看您的模式,并根本禁止该列中的NULL。 – 2011-04-01 08:47:47