28.案例:表间比较IN

     我们知道,IN和NOT IN运算符本质上是OR运算,因而必须从OR运算符对于NULL的处理来考虑IN和NOT IN运算符的运算结果。比如下面的SQL语句是等价的:

--从销售单中检索制作过采购单的人
SELECT * FROM T_SaleBill 
WHERE FBillMakerId IN 
( 
  SELECT FBillMakerId FROM T_PurchaseBill 
)
SELECT * FROM T_SaleBill 
WHERE FBillMakerId IN 
('00006','00004','00001','00002', NULL); 
SELECT * FROM T_SaleBill 
WHERE 
 FBillMakerId='00006' OR FBillMakerId='00004' OR FBillMakerId='00001' OR FBillMakerId='00002' OR FBillMakerId=NULL

而对于NOT IN运算符来说,下面的SQL语句也是等价的: 

SELECT * FROM T_SaleBill 
WHERE FBillMakerId NOT IN 
( 
   SELECT FBillMakerId FROM T_PurchaseBill 
)
SELECT * FROM T_SaleBill 
WHERE FBillMakerId NOT IN('00006','00004','00001','00002', NULL); 
 
SELECT * FROM T_SaleBill 
WHERE NOT(FBillMakerId ='00006' OR FBillMakerId ='00004' OR FBillMakerId 
='00001' OR FBillMakerId ='00002' OR FBillMakerId =NULL); 

     在这种情况下,假设当FBillMakerId等于'00005'时,表达式的输出为:

NOT('00005'='00006' OR '00005'='00004' OR '00005'='00001' OR '00005'='00002' OR '00005'=NULL) 

     我们知道,在SQL中NULL代表“值未知”, “'00005'=NULL”表示判断'00005'是否等于NULL,一个已知的值'00005'是无法确定是否等于一个未知的值的,所以“'00005'=NULL”的返回值也是位置的,所以“'00005'=NULL”的计算结果为NULL。因此上边的条件可以简化为:

NOT(FALSE OR FALSE OR FALSE OR NULL

     根据布尔值与NULL的这个运算特性我们得知“FALSE OR FALSE OR FALSE OR NULL”的运算结果为NULL,而一个未知的值做NOT运算,其结果同样是未知的,因此“NOT NULL”的运算结果为NULL,这样“NOT(FALSE OR FALSE OR FALSE OR NULL)”的运算结果为NULL。既然WHERE条件是未知的,那么结果集中的结果是否符合WHERE条件也就是未知的了,因此检索不出任何数据是非常合理的。

     既然问题出在空值上面,只要将空值从子查询中过滤掉即可。为子查询中的查询语句增加一个WHERE条件,将所有空值过滤掉。SQL语句如下:

SELECT * FROM T_SaleBill 
WHERE FBillMakerId NOT IN 
( 
  SELECT FBillMakerId FROM T_PurchaseBill WHERE FBillMakerId IS NOT NULL 
)

 

posted on 2012-10-24 14:23  凡一二三  阅读(328)  评论(0编辑  收藏  举报