欢迎来到天天文库
浏览记录
ID:34727386
大小:57.18 KB
页数:3页
时间:2019-03-10
《“notin”与“null”的邂逅》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、今天处理了一个因“NOTIN”与“NULL”邂逅导致的问题,值得思考和总结,记录在此,供参考。(感谢John抛出的问题)我们以实验的形式先再现一下这个问题,然后对其分析,最后给出几种解决方案。1.创建实验表T,并分别初始化三条数据,注意T2表中包含一条空(NULL)数据。sec@ora10g>insertintot1values(1);sec@ora10g>insertintot1values(2);sec@ora10g>insertintot1values(3);sec@ora10g>insertintot2values(1);sec@ora10g>
2、insertintot2values(null);sec@ora10g>insertintot2values(3);sec@ora10g>commit;2.确认T1表和T2表的数据内容sec@ora10g>select*fromt1; X---------- 1 2 3sec@ora10g>select*fromt2; X---------- 1 33.再现问题尝试使用“NOTIN”方法获得不在T2表中出现的T1表数据。sec@ora10g>select*
3、fromt1wherexnotin(selectxfromt2);norowsselected问题已重现,明明T1中的数据“2”在T2表中没有,为什么没有返回结果呢?原因:当子查询返回含有“NULL”记录时,使用NOTIN时将不会有返回记录。解析:可以这么理解这个现象:Oracle中的NULL是一个不确定的状态。以T1表中的记录“2”为例,在与T2表中的NULL进行比较时,NULL既可以是“2”,也可以不是“2”,因为判断不了他们的关系,所以只能返回空记录,此乃无奈之举。4.为什么使用“IN”可以返回“正确”的结果?sec@ora10g>select*
4、fromt1wherexin(selectxfromt2); X---------- 1 3这是显然的,因为T2表中确确实实的存在着记录“1”和记录“3”,因此“1”和“3”被返回。不过,注意,NULL依然是一个不确定的状态,因此在T1表中的“2”与NULL比较之后仍然是个不确定的结果,因此“2”是不会被返回的。这里给我们的一个错觉:T1表中的“2”与T2表中NULL不同(他们其实也可能相同)。5.诸多解决方案1)排除“NOTIN”子查询中存在的NULL值sec@ora10g>select*fromt1wher
5、exnotin(selectxfromt2wherexisnotnull); X---------- 22)使用“NOTEXISTS”改写sec@ora10g>select*fromt1wherenotexists(select*fromt2wheret1.x=t2.x); X---------- 23)使用“外连接”改写sec@ora10g>selectt1.*fromt1,t2wheret1.x=t2.x(+)andt2.xisnull; X---------- 2
6、道理是相通的,想想为什么使用“NOTEXISTS”和“外连接”方法改写后就可以成功?(给大家一个机会,这里不赘述。)6.小结这里描述的的案例可以用“陷阱”来形容,不过对于这个“陷阱”我们是有诸多解决方案进行规避的。遇到问题在沉着、冷静+淡定之后,终有柳暗花明之时。希望您也有思考之后豁然开朗之悦。Goodluck.secooler10.02.09--TheEnd--
此文档下载收益归作者所有