網站首頁 編程語言 正文
前言
今天突然想到之前在書上看到的一個例子,竟然想不起來了.
于是翻書找出來,測試一下.
-- 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差異開始測試吧,現在測試使用in、not in 可能帶來的“錯誤”。之所以錯誤,是因為我們總是以自然語言去理解SQL,卻忽略了數學中的邏輯語法。不廢話了,測試看看吧!
【測試一:in子查詢】
--返回在son中存在的所有father的數據 --正確的寫法: select * from father where fid in(select fid from son) --錯誤的寫法: select * from father where fid in(select oid from son)
說明:
兩個查詢都執行沒有出錯,但是第二個tsql的子查詢寫錯了。子查詢(select oid from son)實際單獨執行會出錯,因為表son不存在字段oid,但是在這里系統不會提示錯誤。而且father表有4行數據,所有子查詢掃描了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的處理方式類似。因此第一個子查詢返回了正確的結果集。
【測試二:not ?in子查詢】
--返回在son中不存在的所有father的數據 --錯誤的寫法: 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,結果都不會是true。所以當子查詢存在null時,not in和not exists 在邏輯上是不等價的。
總結:
In 或 not in在SQL語句中經常用到,尤其當子查詢中有空值的時候,要謹慎考慮。因為即使寫了“正確”的腳本,但是返回結果卻不正確,也不出錯。在不是很理解的情況下,最好使用 exists和 not exists來替換。而且exists查詢更快一些,因為只要在子查詢找到第一個符合的值就不繼續往下找了,所以能用exists就用吧。
select *fromfatherawhereexists(select 1fromsonbwherea.fid=b.fid) select * from father awherenotexists(select 1fromsonbwherea.fid=b.fid)
原文鏈接:https://blog.csdn.net/kk185800961/article/details/41764803
相關推薦
- 2022-05-02 深入了解Python?中線程和進程區別_python
- 2023-03-22 C語言中不定參數?...?的語法以及函數封裝_C 語言
- 2022-07-28 C++超詳細講解函數重載_C 語言
- 2022-08-10 淺談Redis變慢的原因及排查方法_Redis
- 2023-04-29 Python如何實用File文件的實現_python
- 2022-09-04 django連接數據庫獲取數據的簡單步驟記錄_python
- 2022-12-10 Input系統之InputReader處理合成事件詳解_Android
- 2022-07-11 Cadence中denalirc的用法總結
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支