暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SQL SERVER中的坑:NOT IN

零壹旅途 2021-06-22
1857

在数据库软件开发中,经常会用到 IN 或 NOT IN 表达式来判断指定的值是否与子查询或列表中的值相匹配。比如,在某个查询中,需要动态地增加一个条件子句,这时候不方便使用联接查询,IN 或 NOT IN 就派上用场了。


举个例子,销售发货单表(SelExport)中有订单编号(OrderNo)字段,现在需要查询已经转为销售发货单的销售订单(SelOrder)的单据张数,可以使用以下语句进行查询:


结果显示,有7911张销售订单已经转到了销售发货单。


此时,如果我还想查询“有多少张销售订单还没有转为销售发货单”,那么很自然地想到,稍微改一下上述语句,将 IN 改为 NOT IN 就能得到我们期望的结果了:

正常执行,返回的结果是0,根据这个结果得出“所有销售订单都已转为销售发货单”的结论,从逻辑上看,是毫无问题的。这个时候,如果不再核对销售订单的总张数,那么可能就掉坑里了。


为了验证这个坑,我们先查询出销售订单总张数:

查询结果显示共有 8318 张销售订单。问题来了!上面已经查询过“已转为销售发货单的销售订单张数”是 7911 张,“未转为销售发货单的销售订单张数”是 0 张,这两个结果的和并不等于销售订单总数:8318。


为什么会这样呢?


其实,MSSQLSERVER的联机文档中有不那么显眼的一句话,已经提示了这个坑!截图如下:

微软的说法是,使用 IN 和 NOT IN 在面对NULL数据时,都会有问题。但实际应用中,使用 IN 没发现有问题,能正确过滤掉NULL值。正是因为使用 IN 没有问题(也许在特别的数据条件下会有问题,但至少到目前我没遇到),所以想当然地认为 NOT IN 也一样,这样就更容易掉坑里。


要避免掉进这个坑,其实很简单,联机文档已经给了答案:过滤掉NULL数据再判断。比如,想查询“有多少张销售订单还没有转为销售发货单”,使用以下语句就没问题了:


走在MS SQL SERVER的金光大道上,一定要常看联机文档,多按F1方能少掉坑。

文章转载自零壹旅途,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论