T-SQL查詢?yōu)楹紊饔肐N和NOT?IN詳解
前言
今天突然想到之前在書上看到的一個(gè)例子,竟然想不起來了.
于是翻書找出來,測試一下.
-- 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 可能帶來的“錯(cuò)誤”。之所以錯(cuò)誤,是因?yàn)槲覀兛偸且宰匀徽Z言去理解SQL,卻忽略了數(shù)學(xué)中的邏輯語法。不廢話了,測試看看吧!
【測試一:in子查詢】
--返回在son中存在的所有father的數(shù)據(jù) --正確的寫法: select * from father where fid in(select fid from son) --錯(cuò)誤的寫法: select * from father where fid in(select oid from son)

說明:
兩個(gè)查詢都執(zhí)行沒有出錯(cuò),但是第二個(gè)tsql的子查詢寫錯(cuò)了。子查詢(select oid from son)實(shí)際單獨(dú)執(zhí)行會(huì)出錯(cuò),因?yàn)楸韘on不存在字段oid,但是在這里系統(tǒng)不會(huì)提示錯(cuò)誤。而且father表有4行數(shù)據(jù),所有子查詢掃描了4次son表,但是第二個(gè)查詢中,實(shí)際也只掃描了1次son表,也就是son表沒有用到。
即使這樣寫也 不會(huì)出錯(cuò): select*fromfatherwherefidin(selectoid)
這個(gè)查詢的意思是,表father中每行的fid與oid比較,相同則返回值。
實(shí)際查詢是這樣的: select * from father where fid = oid
測試一中,fid in(select fid from son)子查詢中包含null值,所以 fid in(null)返回的是一個(gè)未知值。但是在刷選器中,false和unknown的處理方式類似。因此第一個(gè)子查詢返回了正確的結(jié)果集。

【測試二:not in子查詢】
--返回在son中不存在的所有father的數(shù)據(jù) --錯(cuò)誤的寫法: select * from father where fid not in(select fid from son) --錯(cuò)誤的寫法: 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)永遠(yuǎn)不會(huì)返回false,只反會(huì)true或unknown,所以謂詞fidnot in(2,3,null)只返回not true 或not unknown,結(jié)果都不會(huì)是true。所以當(dāng)子查詢存在null時(shí),not in和not exists 在邏輯上是不等價(jià)的。
總結(jié):
In 或 not in在SQL語句中經(jīng)常用到,尤其當(dāng)子查詢中有空值的時(shí)候,要謹(jǐn)慎考慮。因?yàn)榧词箤懥?ldquo;正確”的腳本,但是返回結(jié)果卻不正確,也不出錯(cuò)。在不是很理解的情況下,最好使用 exists和 not exists來替換。而且exists查詢更快一些,因?yàn)橹灰谧硬樵冋业降谝粋€(gè)符合的值就不繼續(xù)往下找了,所以能用exists就用吧。
select *fromfatherawhereexists(select 1fromsonbwherea.fid=b.fid) select * from father awherenotexists(select 1fromsonbwherea.fid=b.fid)
到此這篇關(guān)于T-SQL查詢?yōu)楹紊饔?nbsp;IN和NOT IN詳解的文章就介紹到這了,更多相關(guān)T-SQL查詢慎用 IN和NOT IN內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SQL Server Management Studio(SSMS)復(fù)制數(shù)據(jù)庫的方法
這篇文章主要為大家詳細(xì)介紹了如何利用SQL Server Management Studio復(fù)制數(shù)據(jù)庫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
淺析SQL Server的嵌套存儲(chǔ)過程中使用同名的臨時(shí)表怪像
這篇文章主要介紹了淺析SQL Server的嵌套存儲(chǔ)過程中使用同名的臨時(shí)表怪像,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02
SQL Server中使用判斷語句(IF ELSE/CASE WHEN )案例
這篇文章主要介紹了SQL Server中使用判斷語句(IF ELSE/CASE WHEN )案例,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
SQL Server 監(jiān)控磁盤IO錯(cuò)誤,msdb.dbo.suspect_pages
suspect_pages 表位于 msdb 數(shù)據(jù)庫中,是在 SQL Server 2005 中引入的。用于維護(hù)有關(guān)可疑頁的信息的 suspect_pages2014-10-10
sql?server如何去除數(shù)據(jù)中的一些無用的空格
這篇文章主要介紹了sql?server去除數(shù)據(jù)中的一些無用的空格,本文給大家提到了一些常用的函數(shù),結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
SQL中聚類后字段數(shù)據(jù)串聯(lián)字符串方法常見示例代碼
這篇文章主要介紹了SQL中聚類后字段數(shù)據(jù)串聯(lián)字符串方法常見的方法,文中通過代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2025-01-01
升級(jí)SQL Server 2014的四個(gè)要點(diǎn)要注意
升級(jí)一個(gè)關(guān)鍵業(yè)務(wù)SQL Server實(shí)例并不容易,它要求有周全的計(jì)劃。計(jì)劃不全會(huì)增加遇到升級(jí)問題的可能性,從而影響或延遲SQL Server 2014的升級(jí)。在規(guī)劃SQLServer 2014升級(jí)時(shí),有一些注意事項(xiàng)有助于避免遇到升級(jí)問題,需要的朋友可以參考下2015-08-08
在SQL Server中使用SQL語句查詢一個(gè)存儲(chǔ)過程被其它所有的存儲(chǔ)過程引用的存儲(chǔ)過程名
在項(xiàng)目開發(fā)中如果有時(shí)修改了一個(gè)存儲(chǔ)過程,但是如何能夠快速的查找到使用了這個(gè)存儲(chǔ)過程的其它存儲(chǔ)過程呢2012-06-06

