SQL Server 2000奇怪的子查询问题

时间:2011-04-01 07:19:55

标签: sql database sql-server-2000 subquery

有一种奇怪的行为让我发疯。

我在旧的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

正确地返回没有权限的用户。

那么,问题在哪里?

为什么第一个不起作用?

1 个答案:

答案 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);