T-SQL查詢?yōu)楹紊饔肐N和NOT?IN詳解
前言
今天突然想到之前在書上看到的一個例子,竟然想不起來了.
于是翻書找出來,測試一下.
-- drop table father,son create table father(fid int,name varchar(10),oid int) create table son(sid int,name varchar(10),fid int) insert into father(fid,name,oid) values(1,'father',5),(2,'father',9),(3,'father',null),(4,'father',0) insert into son(sid,name,fid) values(1,'son',2),(2,'son',2),(3,'son',3),(4,'son',null),(5,'son',null) select * from father select * from son
in和exists差異開始測試吧,現(xiàn)在測試使用in、not in 可能帶來的“錯誤”。之所以錯誤,是因為我們總是以自然語言去理解SQL,卻忽略了數(shù)學中的邏輯語法。不廢話了,測試看看吧!
【測試一:in子查詢】
--返回在son中存在的所有father的數(shù)據(jù) --正確的寫法: select * from father where fid in(select fid from son) --錯誤的寫法: select * from father where fid in(select oid from son)
說明:
兩個查詢都執(zhí)行沒有出錯,但是第二個tsql的子查詢寫錯了。子查詢(select oid from son)實際單獨執(zhí)行會出錯,因為表son不存在字段oid,但是在這里系統(tǒng)不會提示錯誤。而且father表有4行數(shù)據(jù),所有子查詢掃描了4次son表,但是第二個查詢中,實際也只掃描了1次son表,也就是son表沒有用到。
即使這樣寫也 不會出錯: select*fromfatherwherefidin(selectoid)
這個查詢的意思是,表father中每行的fid與oid比較,相同則返回值。
實際查詢是這樣的: select * from father where fid = oid
測試一中,fid in(select fid from son)子查詢中包含null值,所以 fid in(null)返回的是一個未知值。但是在刷選器中,false和unknown的處理方式類似。因此第一個子查詢返回了正確的結(jié)果集。
【測試二:not in子查詢】
--返回在son中不存在的所有father的數(shù)據(jù) --錯誤的寫法: select * from father where fid not in(select fid from son) --錯誤的寫法: select * from father where fid not in(select oid from son) --正確的寫法: select * from father where fid not in(select fid from son where fid is not null)
說明:
查看select fid from son,子查詢中有空值null,子查詢中的值為(2,3,null),謂詞fid in(2,3,null)永遠不會返回false,只反會true或unknown,所以謂詞fidnot in(2,3,null)只返回not true 或not unknown,結(jié)果都不會是true。所以當子查詢存在null時,not in和not exists 在邏輯上是不等價的。
總結(jié):
In 或 not in在SQL語句中經(jīng)常用到,尤其當子查詢中有空值的時候,要謹慎考慮。因為即使寫了“正確”的腳本,但是返回結(jié)果卻不正確,也不出錯。在不是很理解的情況下,最好使用 exists和 not exists來替換。而且exists查詢更快一些,因為只要在子查詢找到第一個符合的值就不繼續(xù)往下找了,所以能用exists就用吧。
select *fromfatherawhereexists(select 1fromsonbwherea.fid=b.fid) select * from father awherenotexists(select 1fromsonbwherea.fid=b.fid)
到此這篇關于T-SQL查詢?yōu)楹紊饔?nbsp;IN和NOT IN詳解的文章就介紹到這了,更多相關T-SQL查詢慎用 IN和NOT IN內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SQL Server 2012使用Offset/Fetch Next實現(xiàn)分頁數(shù)據(jù)查詢
在Sql Server 2012之前,實現(xiàn)分頁主要是使用ROW_NUMBER(),在SQL Server2012,可以使用Offset ...Rows Fetch Next ... Rows only的方式去實現(xiàn)分頁數(shù)據(jù)查詢,具體代碼詳解大家參考下本文2017-07-07sqlserver數(shù)據(jù)庫規(guī)模膨脹太大怎么優(yōu)化
數(shù)據(jù)庫規(guī)模膨脹是SQLServer數(shù)據(jù)庫運維中常見的問題之一,本文介紹了一些緩解膨脹問題的方法,包括增加內(nèi)存、數(shù)據(jù)壓縮、數(shù)據(jù)庫分區(qū)等,在實踐過程中,應根據(jù)具體情況,采取適當?shù)姆椒?以達到最優(yōu)的緩解膨脹問題的效果2024-02-02DBCC CHECKIDENT 重置數(shù)據(jù)庫標識列從某一數(shù)值開始
DBCC CHECKIDENT 重置數(shù)據(jù)庫標識列從某一數(shù)值開始2009-10-10SqlServer Mysql數(shù)據(jù)庫修改自增列的值及相應問題的解決方案
這篇文章主要介紹了SqlServer Mysql數(shù)據(jù)庫修改自增列的值及相應問題的解決方案的相關資料,需要的朋友可以參考下2016-01-01深入分析MSSQL數(shù)據(jù)庫中事務隔離級別和鎖機制
事務隔離級別簡單的說,就是當激活事務時,控制事務內(nèi)因SQL語句產(chǎn)生的鎖定需要保留多入,影響范圍多大,以防止多人訪問時,在事務內(nèi)發(fā)生數(shù)據(jù)查詢的錯誤。設置事務隔離級別將影響整條連接。2014-08-08