SQL Server 2000奇怪的子查询问题

标签 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

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

那么,问题出在哪里呢?

为什么第一个不起作用?

最佳答案

这是预期的行为。
这是预期的,因为 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);

关于SQL Server 2000奇怪的子查询问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5510278/

相关文章:

单查询中的MySQL双查询

c# - SQL 2000 的 NHibernate 变量限制

sql-server - MS-SQL Server 2000慢速全文本索引

c# - 查询代码非常慢,但在 SSMS 中查询速度很快

sql - dense_rank 在 SQL 服务器上填充 tempdb?

javascript - Web 应用程序的问题

mysql - 不唯一/表别名 'respite'

java - SQL 更新列从一个表到另一个

php - 将所有 mysql 错误记录到数据库或排序?

php - PHP 用户类应该扩展数据库类吗?