mssql sqlserver not in和not exists关键字的区别及注意事项


摘要:
not in和not exists关键字分别对应in和exists关键字的相反操作,
在sql中使用in和exists关键字可以完成达到相同的功能,但是在not in和not exists中需要特别注意
当列中存在null值时,子查询得到的结果不同


例:

 create table [maomao365.com_a]
   (keyIdA int,infoA nvarchar(20))
 create table [maomao365.com_b]
   (keyIdB int,infoB nvarchar(20))
go


一、不含null值的子查询

truncate table [maomao365.com_a]
truncate table [maomao365.com_b]
  insert into [maomao365.com_a]
 (keyIdA,infoA)values(1,N'sql博客'),
(2,N'猫猫教程')

  insert into [maomao365.com_b]
 (keyIdB,infoB)values(1,N'测试') 

  select  keyIdA,infoA from [maomao365.com_a] 
  where not exists(
     select null from [maomao365.com_b] 
       where infoB =  infoA
   )
  
   select keyIdA,infoA from [maomao365.com_a]
    where infoA not  in (
       select infoB from  [maomao365.com_b]
      )
------以上sql返回的结果相同


二、含null值的子查询


当子查询中包含null值时,not in 和not exists 执行后的效果并不相同,返回的结果不相同。

    truncate table [maomao365.com_a]
truncate table [maomao365.com_b]
  insert into [maomao365.com_a]
 (keyIdA,infoA)values(1,N'sql博客'),
(2,N'猫猫教程')

  insert into [maomao365.com_b]
    (keyIdB,infoB)values(1,N'测试') ,
    (null,N'测试2')

  select  keyIdA,infoA from [maomao365.com_a] 
  where not exists(
     select null from [maomao365.com_b] 
       where infoB =  infoA
   )
  
   select keyIdA,infoA from [maomao365.com_a]
    where infoA not  in (
       select infoB from  [maomao365.com_b]
      )
--执行以上两段sql脚本,我们发现not in 子查询未返回任何信息,出现此现象的原因为:
  null值同任何值比较都会得到unknown结果,如果想让null值返回true,须使用is null 判断
 例:
    1 in (1,null) 返回true 
    1 not in (1,null) 返回unknown,因为sql server不知道1和null的比较关系,
      所以返回not unknown


注意事项:
为了避免包含null值的not in查询,我们应使用is not null对子查询数据进行过滤,
not in应改写为以下sql脚本
select keyIdA,infoA from [maomao365.com_a]
where infoA not in (
select infoB from [maomao365.com_b]
where infoB is not null
)