<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SQL查詢:慎用 IN 和 NOT IN

          共 2609字,需瀏覽 6分鐘

           ·

          2021-07-09 02:18

          點(diǎn)擊關(guān)注上方“SQL數(shù)據(jù)庫開發(fā)”,

          設(shè)為“置頂或星標(biāo)”,第一時間送達(dá)干貨
          SQL專欄
          SQL基礎(chǔ)知識第二版
          SQL高級知識第二版

          作者:薛定諤的DBA

          blog.csdn.net/kk185800961/

          今天突然想到之前在書上看到的一個例子,竟然想不起來了.

          于是翻書找出來,測試一下.

          -- 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ù)學(xué)中的邏輯語法。不廢話了,測試看看吧!

          【測試一: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)實際單獨(dú)執(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)永遠(yuǎn)不會返回false,只反會true或unknown,所以謂詞fidnot in(2,3,null)只返回not true 或not unknown,結(jié)果都不會是true。所以當(dāng)子查詢存在null時,not in和not exists 在邏輯上是不等價的。

          總結(jié)

          In 或 not in在SQL語句中經(jīng)常用到,尤其當(dāng)子查詢中有空值的時候,要謹(jǐn)慎考慮。因為即使寫了“正確”的腳本,但是返回結(jié)果卻不正確,也不出錯。

          在不是很理解的情況下,最好使用 exists和 not exists來替換。而且exists查詢更快一些,因為只要在子查詢找到第一個符合的值就不繼續(xù)往下找了,所以能用exists就用吧。


          最后給大家分享我寫的SQL兩件套:《SQL基礎(chǔ)知識第二版》《SQL高級知識第二版》的PDF電子版。里面有各個語法的解釋、大量的實例講解和批注等等,非常通俗易懂,方便大家跟著一起來實操。

          有需要的可以下載學(xué)習(xí),只需要在下面的公眾號「數(shù)據(jù)前線(非本號),后臺回復(fù)關(guān)鍵字:SQL,就行

          數(shù)據(jù)前線

          后臺回復(fù)關(guān)鍵字:1024,獲取一份精心整理的技術(shù)干貨
          后臺回復(fù)關(guān)鍵字:進(jìn)群,帶你進(jìn)入高手如云的交流群。
          推薦閱讀

          瀏覽 67
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  狼人综合影院啊啊啊啊 | 中文字幕的乱伦 | 中国老熟女~x88AV | 亚洲成人在线观看视频 | 日本老熟女视频 |