SQL Server:为什么比较 null=value 对于 NOT IN 返回 true?

2023-11-22

为什么比较value to null返回 false,除非使用NOT IN,哪里返回 true?


给定一个查询来查找所有 stackoverflow 用户have a post:

SELECT * FROM Users
WHERE UserID IN (SELECT UserID FROM Posts)

这按预期工作;我得到了所有拥有帖子的用户的列表。

现在查询逆;查找所有 stackoverflow 用户don't有一个帖子:

SELECT * FROM Users
WHERE UserID NOT IN (SELECT UserID FROM Posts)

这不会返回任何记录,这是不正确的。

Given hypothetical data1

Users              Posts
================   ===============================
UserID  Username   PostID   UserID  Subject
------  --------   -------  ------  ----------------
1       atkins     1        1       Welcome to stack ov...
2       joels      2        2       Welcome all!
...     ...        ...      ...
399573  gt6989b    ...      ...
...     ...        ...      ...
                   10592    null    (deleted by nsl&fbi...
                   ...      ... 

并假设 NULL 的规则:

  • NULL = NULL评估为未知
  • NULL <> NULL评估为未知
  • value = NULL评估未知

如果我们查看第二个查询,我们感兴趣的是查找 Users.UserID 所在的所有行not在 Posts.UserID 列中找到。我将按照逻辑进行如下操作:

检查用户ID 1

  • 1 = 1返回真。所以我们得出结论,该用户有一些帖子,并且不将它们包含在输出列表中

现在检查用户 ID 2:

  • 2 = 1返回 false,所以我们继续寻找
  • 2 = 2返回 true,因此我们得出结论该用户有一些帖子,并且不将它们包含在输出列表中

现在检查用户ID 399573

  • 399573 = 1返回 false,所以我们继续寻找
  • 399573 = 2返回 false,所以我们继续寻找
  • ...
  • 399573 = null返回未知,所以我们继续寻找
  • ...

我们没有找到 UserID 399573 的帖子,因此我们将把他包含在输出列表中。

但 SQL Server 不这样做。如果你的中有一个NULLin列表,然后突然找到一个匹配项。它突然找到了匹配。突然399573 = null评估为真。

为什么比较value to null返回未知,除非它返回 true ?

Edit:我知道我可以通过专门排除空值来解决这个nonsensical行为:

SELECT * FROM Users
WHERE UserID NOT IN (
   SELECT UserID FROM Posts
   WHERE UserID IS NOT NULL)

但我不应该这样做,据我所知,没有它布尔逻辑应该没问题 - 因此我的问题。

脚注

  • 1 hypothetical data; if you don't like it: make up your down.
  • celko 现在有了自己的标签

常见问题,预设答案:

NOT IN 子句的行为可能会令人困惑,因此需要一些解释。考虑以下查询:

SELECT LastName, FirstName FROM Person.Contact WHERE LastName NOT IN('Hedlund', 'Holloway', NULL)

尽管 AdventureWorks.Person.Contact 中有一千多个不同的姓氏,但该查询不会返回任何内容。对于初学者数据库程序员来说,这可能看起来违反直觉,但实际上是完全有道理的。该解释由几个简单的步骤组成。首先,考虑以下两个查询,它们显然是等价的:

SELECT LastName, FirstName FROM Person.Contact

WHERE LastName IN('Hedlund', 'Holloway', NULL)



SELECT LastName, FirstName FROM Person.Contact

WHERE LastName='Hedlund' OR LastName='Holloway' OR LastName=NULL

请注意,两个查询都会返回预期结果。现在,让我们回顾一下德摩根定理,该定理指出:

not (P and Q) = (not P) or (not Q)

not (P or Q) = (not P) and (not Q)

我从维基百科(http://en.wikipedia.org/wiki/De_Morgan_duality)剪切和粘贴。将 DeMorgan 定理应用于此查询,可以得出这两个查询也是等价的:

SELECT LastName, FirstName FROM Person.Contact WHERE LastName NOT IN('Hedlund', 'Holloway', NULL)



SELECT LastName, FirstName FROM Person.Contact

WHERE LastName<>'Hedlund' AND LastName<>'Holloway' AND LastName<>NULL

最后一个 LastNameNULL 永远不可能为 true

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL Server:为什么比较 null=value 对于 NOT IN 返回 true? 的相关文章

  • 如何返回调用不同数据库中的存储过程的远程数据库名称?

    我在一个 SQL Server 2008 R2 上有许多不同的数据库 为了便于论证 我们将它们称为 DB A DB B 和 DB C 我被要求开发一个将存在于 DB A 上的存储过程 该存储过程将用于删除和创建索引 并在 DB A 的表中存
  • 淹没在空无的海洋中

    我继承的一个应用程序跟踪对材料样品执行的实验室测试结果 数据存储在单个表 tblSampleData 中 其主键为 SampleID 并有 235 列代表潜在的测试结果 问题是每个样本仅执行少量测试 因此每行包含超过 200 个空值 实际上
  • 关于数据库变更的通知

    我正在尝试一种场景 其中我想使用任何用户提交的更改来更新在不同 PC 上运行的桌面 UI 例如 Application1 安装在 PC1 PC2 和 PC3 上 假设所有 PC 都运行此应用程序 假设 PC1 上的用户 1 更改数据并提交到
  • 针对 SQL Server 的 SQL 查询的执行日期时间

    我曾经发现过这个很好的查询here https dba stackexchange com a 135080 43889 我想将查询的执行时间添加到以下查询中 USE master go SELECT sdest DatabaseName
  • T-SQL:检查电子邮件格式

    我有这样的场景 我需要物理数据库中的数据完整性 例如 我有一个变量 email address VARCHAR 200 我想检查一下值是否为 email address是电子邮件格式 有人知道如何检查 T SQL 中的格式吗 非常感谢 我使
  • 如何增加每次 INSERT INTO 迭代的值?

    我有一个查询 如下所示 第 1 列位于 另一列是 varchar 100 INSERT INTO TABLE1 column1 column2 SELECT MAX column1 FROM TABLE1 1 anotherColumn F
  • SQL 选择另一列中具有最大值的列

    我有一个看起来像这样的表 Name Group Value A 1 0 B 1 2 C 1 5 D 2 6 E 2 0 F 3 3 我想选择每组中具有最大值的名称 例如 有 3 个组 因此结果将是 Name C because it has
  • 管理员无法管理 SQL Server 报告服务

    我正在 SQL Server 2008 Standard 上运行 SQL Server Reporting Services 并尝试使网页正常工作 我需要做什么才能获得 RS 报表管理器 报表服务连接 首先将我视为管理员 以便我可以更改我的
  • 从 SQL XML 列中的元素获取属性名称

    对于此 xml 在 SQL 2005 XML 列中
  • C# 通过实体框架调用 SQL Server 用户定义的函数

    我不敢相信我必须问这个问题 但我被困住了 我花了三个小时试图解决这个问题 但我被困住了 我可以在以前版本的 C 中执行此操作 但我卡住了 在继续之前 我正在研究堆栈 视觉工作室2012 SQL Server 2012 NET Framewo
  • 如何在 JavaScript 中检查未定义或 null 变量?

    我们经常在 JavaScript 代码中使用以下代码模式 if typeof some variable undefined some variable null Do something with some variable 是否有一种不
  • 使用变量获取 SQL xml 属性值

    我有一个 SQL 函数 它接受一个名为attribute 这是我想要从中获取值的 xml 属性 xmlPath是完整的 XML 字符串 我的 xml 看起来像这样
  • 检查 SQL MAX() 函数返回 null

    我的问题是 如果我的表为空或者我使用 max 函数的列没有我指定的值 那么为什么 sqlDataReader hasRows TRUE 它给出了空记录 我该如何解决这个问题 提前致谢 像 MAX 这样的聚合函数将始终为每组返回一行 就您而言
  • 带逗号和句点的 SQL Server 2005 货币格式

    有没有办法在 SQL Server 2005 中转换货币字段以对其进行格式化 例如 该字段包含 99966 00 我们希望以这种格式返回 99 966 00 convert varchar cast SalesProducts Price
  • 如何在行的列中插入当前日期

    如何将当前日期插入 MS SqlServer Mgm Studio 中 编辑数据 视图中的行列中 我想得到等价的值GetDate 函数调用 这是我希望能澄清问题的图片 您无法键入函数 因此请键入日期或以下解决方案之一 创建默认值GetDat
  • 检索使用 Uniqueidentifier 插入的最后一行,它不是 IDENTITY

    我对一个查询感到困惑 我需要找出表中添加的最后一行 其中有一列数据类型为 Uniqueidentifier 列是 aspnet Applications ApplicationId 注意 该列是Uniqueidentifier 它不是IDE
  • SQL Server 2008中的分割函数

    I have Table1像这样的列 ID Name 1 MSSQL 2 MySQl 3 Oracle In Table2 我有一个像这样的专栏 Databasename 1 3 2 1 2 我的输出应该是 Databasename MSS
  • 隐藏 SSRS 嵌套组同时显示详细信息行

    我有一个分层数据集 如下所示 Group1 Group2 Group3 Group4 Group5 Detail Food Fruit Red Apple Apple Food Fruit Orange Orange Orange Food
  • 如何在数据透视 SQL 查询中用零替换 null

    我正在尝试获取按年和按月的销售量 例如 select from select year InvDt as Year left datename Month InvDt 3 as Month InvAmnt as Amount from tb
  • 为什么这个 CTE 比使用临时表慢得多?

    自从我们的数据库最近更新以来 我们遇到了一个问题 我进行了此更新 我在这里感到内疚 从那时起 使用的其中一个查询要慢得多 我尝试修改查询以获得更快的结果 并设法使用临时表实现我的目标 这还不错 但我无法理解为什么该解决方案比基于 CTE 的

随机推荐