数据库

本类阅读TOP10

·SQL语句导入导出大全
·SQL Server日期计算
·SQL语句导入导出大全
·SQL to Excel 的应用
·Oracle中password file的作用及说明
·MS SQLServer OLEDB分布式事务无法启动的一般解决方案
·sqlserver2000数据库置疑的解决方法
·一个比较实用的大数据量分页存储过程
·如何在正运行 SQL Server 7.0 的服务器之间传输登录和密码
·SQL中两台服务器间使用连接服务器

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
了解一下NULLs怎样影响IN和EXISTS

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

如果你的数据库设计在任何一栏中都允许NULL值的话,你需要了解一下,在你的查询语句中,不同的子句是怎样对待这一问题的。
  
  从表面上看,可能显示出这样的情形,即SQL子句IN与EXISTS可以互换。然而,在处理NULL值时,它们的表现截然不同,而且得到的结果也很可能不同。问题源于这样一个事实,即在一个Oracle数据库中,一个NULL值意味着未知,因此,对一个NULL值的任何比较或操作也都是无效的,而任何返回NULL的测试也都被忽视了。例如,以下这些查询语句都不会返回任何行:
  
  select 'true' from dual where 1 = null;
  
  select 'true' from dual where 1 != null;
  
  值1既不能说是等于NULL,也不能说是不等于NULL。只有是NULL的时候才会返回一个真正的NULL值并返回一行。
  
  select 'true' from dual where 1 is null;
  
  select 'true' from dual where null is null;
  
  当你使用IN时,相当于你告诉SQL接受一个值,并将它与某个清单中使用=的每一个值或一组值进行比较。只要存在了任何NULL值,就不会返回任何行,纵使两个值都是NULL也不行。
  
  select 'true' from dual where null in (null);
  
  select 'true' from dual where (null,null) in ((null,null));
  
  select 'true' from dual where (1,null) in ((1,null));
  
  一个IN从功能上等同于=ANY子句:
  
  select 'true' from dual where null = ANY (null);
  
  select 'true' from dual where (null,null) = ANY ((null,null));
  
  select 'true' from dual where (1,null) = ANY ((1,null));
  
  当你使用一种与EXISTS等同的格式时,SQL会计算行数,却忽视子查询中的值,就算你返回NULL也一样。
  
  select 'true' from dual where exists (select null from dual);
  
  select 'true' from dual where exists (select 0 from dual where null is null);
  
  从逻辑上看,IN与EXISTS是一样的。IN子句在外部查询中比较子查询返回的值,并过滤掉行;EXISTS子句在子查询内部比较那些值并过滤掉行。在出现NULL值的情况下,作为结果而出现的那些行是相同的。
  
  selectename from emp where empno in (select mgr from emp);
  
  selectename from emp e where exists (select 0 from emp where mgr = e.empno);
  
  不过,当逻辑被转变成使用NOT IN和NOT EXISTS时,问题就出现了,这两个语句会返回不同的行(第一个查询会返回0行;第二个返回意想的数据-它们是不同的查询):
  
  selectename from emp where empno not in (select mgr from emp);
  
  selectename from emp e where not exists (select 0 from emp where mgr =e.empno);
  
  NOT IN子句实际上与用=比较每一个值相同,如果任何一个测试为FALSE 或NULL的话,它就会失败。例如:
  
  select 'true' from dual where 1 not in (null,2);
  
  select 'true' from dual where 1 != null and 1 != 2;
  
  select 'true' from dual where (1,2) not in ((2,3),(2,null));
  
  select 'true' from dual where (1,null) not in ((1,2),(2,3));
  
  这些查询不会返回任何行。而第二个更值得怀疑,1!=NULL是NULL,因此对整个WHERE条件来说都是错误的。它们会这样运行:
  
  select 'true' from dual where 1 not in (2,3);
  
  select 'true' from dual where 1 != 2 and 1 != 3;
  
  只要你在结果中阻止系统返回NULL,在这之前你还是可以使用NOT IN查询(同样,这些都能运行,不过我假定empno不是NULL,在我们这个案例中,这是一个很好的假设):
  
  selectename from emp where empno not in (select mgr from emp where mgr is not null);
  
  selectename from emp where empno not in (select nvl(mgr,0) from emp);
  
  由于了解了IN,EXISTS,NOT IN,以及NOT EXISTS之间的差别,当一个子查询的数据中出现NULL时,你就可以避免一个非常普遍的问题了。


相关文章

相关软件