SQL 的 NOT IN
子句和 NULL 值问题
SQL 中的 NOT IN
运算符旨在选择在指定值集中未找到列值的行。但是,当比较集包含 NULL
值时,此运算符会出现意外行为。本文解释了此行为并提供了解决方案。
问题:
考虑这样一种场景,您尝试在一个数据库 (Inventory
) 中查找子集数据库 (Subset
) 中不存在的产品。使用 NOT IN
的常见方法可能如下所示:
<code class="language-sql">SELECT stock.IdStock, stock.Descr FROM [Inventory].[dbo].[Stock] stock WHERE stock.IdStock NOT IN (SELECT foreignStockId FROM [Subset].[dbo].[Products]);</code>
如果子查询 (SELECT foreignStockId FROM [Subset].[dbo].[Products]
) 返回任何 NULL
值,则整个 NOT IN
条件将变得不确定,从而导致结果集为空 — 即使 IdStock
中有 [Inventory].[dbo].[Stock]
值是 不出现在[Subset].[dbo].[Products]
中。
为什么会发生这种情况:
SQL 使用三值逻辑:TRUE
、FALSE
和 UNKNOWN
。 将值与 NULL
进行比较时,结果始终为 UNKNOWN
。 NOT IN
本质上是检查 FALSE
所有 比较的值是否为 。 由于 UNKNOWN
不是 FALSE
,子查询结果集中的任何 NULL
都会使整个 NOT IN
条件计算为空集。
解决方案:
要避免此问题,请使用以下方法之一:
1。显式排除 NULL: 修改子查询以过滤掉 NULL
值:
<code class="language-sql">SELECT stock.IdStock, stock.Descr FROM [Inventory].[dbo].[Stock] stock WHERE stock.IdStock NOT IN (SELECT foreignStockId FROM [Subset].[dbo].[Products] WHERE foreignStockId IS NOT NULL);</code>
2。使用 NOT EXISTS
: 这种方法因其清晰和高效而通常是首选:
<code class="language-sql">SELECT stock.IdStock, stock.Descr FROM [Inventory].[dbo].[Stock] stock WHERE NOT EXISTS (SELECT * FROM [Subset].[dbo].[Products] p WHERE p.foreignStockId = stock.IdStock);</code>
NOT EXISTS
子句检查子查询中是否存在与条件匹配的 no 行。 它可以正确处理 NULL
值,无需显式排除。
通过了解 NULL
值和 NOT IN
运算符之间的交互,您可以编写更健壮、更可靠的 SQL 查询。 在处理比较集中的潜在 NOT EXISTS
值时,NULL
替代方案通常是更干净、更高效的解决方案。
以上是当子查询中存在 NULL 值时,为什么我的 SQL'NOT IN”查询没有返回结果?的详细内容。更多信息请关注PHP中文网其他相关文章!