咱們接着上一篇的內容繼續。這一篇主要回顧子查詢,聯合查詢,復制表這三類內容。
上一部分基本上都是簡單的Select查詢,即從單個數據庫表中檢索數據的單條語句,但是實際應用中的業務邏輯往往會非常復雜,所以會用到一些比較復雜的查詢,如子查詢,聯合查詢。
1.子查詢
當一個查詢是另一個查詢的條件時,稱為子查詢。但是說到子查詢又不的不說它與嵌套查詢兩者的區別,下面一張圖來說明
下面再用一條sql語句來說明他們的關系。
其中在查詢中又分為嵌套子查詢和相關子查詢,他們之間的區別就是查詢是否依賴與外部的查詢,嵌套子查詢的執行不依賴與外部的查詢,而相關子查詢的執行依賴於外部查詢。
select * from Books where 價格 < (select AVG(價格) from Books) --查詢所有價格高於平均價格的書信息
上邊的一條sql語句便是嵌套子查詢,來分析他的執行過程。
①先執行子查詢,即查詢出Books表中書的平均價格,然后將結果傳遞給父查詢,作為父查詢的條件。
②執行父查詢,返回結果。
select * from Books as a where 價格 < (select AVG(價格) from Books as b where a.類編號=b.類編號)--查詢表中大於該類圖書價格平均值的圖書信息
上邊一條語句便是嵌套子查詢,來分析他的執行過程。
①先從父查詢中讀取一個數據,即類編號,然后將類編號傳遞給子查詢。
②執行子查詢,將這個類編號的書的平均價格查詢出來,並將其傳遞給父查詢。
③父查詢判斷這條數據是否滿足條件,不滿足就排除,滿足則保留。
④然后父查詢獲取下一條數據中的類編號,重復①到③步驟,直到外層所有數據被處理完。
2.表聯合查詢
SQL最強大的功能之一就是能在數據查詢的執行中聯結(join)表。聯結是利用SQL的SELECT能執行的最重要的操作,在能夠有效地使用聯結前,先了解一下數據庫的三個范式。
1NF(原子性):字段不可再分,否則就不是關系型數據庫。例:學生表里,一個列里同時存儲【姓名】和【年齡】,這個就不符合原子性。
2NF(唯一性):有主鍵,非主鍵字段全部依賴於主鍵;或者說,一個表中只能說明一個事務。例:學生表里,主鍵是【學號】,有一列存儲【班級總人數】,【班級總人數】和主鍵【學號】沒有依賴,這種情況不符合唯一性。
3NF(無傳遞依賴):主鍵字段不能相互依賴,不能傳遞依賴。例:學生表里主鍵是【學號】,存儲一列為【所屬班級】,又存儲一列【班級總人數】,【所屬班級】依賴【學號】,【班級總人數】依賴【所屬班級】,有傳遞依賴,不符合第三范式。
三范式是解決了數據庫的冗余問題,但是在很多業務邏輯下,必須同時查詢兩個或兩個以上的表,這個時候就用到了表的聯合(結)查詢。
笛卡兒積( 笛卡兒積(cartesian product):由沒有聯結條件的表關系返回的結果為笛卡兒積。即將是第一個表中的行數乘以第二個表中的行數。
聯合查詢,就是先求出所查表的笛卡爾積之后,在對笛卡兒積進行篩選。
而連接類型又分為好幾種,如下圖所示。
- (Inner) Join: 如果表中有至少一個匹配,則返回行
- Left Join: 即使右表中沒有匹配,也從左表返回所有的行
- Right Join: 即使左表中沒有匹配,也從右表返回所有的行
- Full Join: 只要其中一個表中存在匹配,就返回行
- Cross Join: 就是返回兩個關聯表的笛卡兒積
內連接(Inner Join)是最常用的連接操作。內連接有兩種不同的語法 ,一種是顯示連接符號,另一種是隱式鏈接符號,他們的區別就是用不用Join關鍵字。
語法:select <要選字段> from <主要資料表> <join方式> <次要資料表> [on <join 規則>] --在內連接中,Join規則不相符的都會被排除:排他性 寫法1:select * from A inner join B on A.name=B.name --顯示連接符號 寫法2:select * from A,B where A.name=B.name --隱式鏈接符號
--對照上圖,內連接查詢出a和b兩表的公共集c
外連接並不要求連接的兩表的每一條記錄在對方表中都一條匹配的記錄,要保留所有記錄的表(即使這條記錄沒有匹配也要保留)稱為保留表,保留表在join關鍵字左邊的連接就稱為左連接,在右邊就稱為右連接,當兩表記錄都要保存時,稱為全外連接。左外連接查詢時,如果右表中無匹配記錄, 來自於右表的所有列的值設為 NULL,右外連接,全外連接也是這種情況。
語法:select <要選字段> from <left資料表> <left|right>[outer] join <right資料表> [on <join 規則>] --在外連接中:包容性 左外連接:select * from A left (outer)join B on A.name=B.name --對照上圖即左外連接查詢出表a的所有集合和b中和a公共集合 a1+c 右外連接:select * from A right(outer)join B on A.name=B.name --對照上圖即右外連接查詢出表a的所有集合和b中和a公共集合 b1+c
全外連接:select * from A full(outer)join B on A.name=B.name --對照上圖即全外連接查詢出表a的所有集合和b中所有集合 a1+c+b1
3.復制表
有時候需要將一個表的數據直接導入到一個新表中,這時候可以用select...into...from或者insert into...select,不過兩者有區別。
select * into NewTable from Books --使用這條語句時,數據庫中必須原先不存在表NewTable ,若數據庫中原先有此表,則會報錯 insert into NewTable select * from Books --這條語句中,數據庫中必須原先存在表NewTable, 若不存在,則執行報錯
還有一個問題需注意:在使用復制表語句時,只會復制表的數據和結構,但是表中的主鍵,外鍵,約束,索引這些信息不會復制過來。
這個就先寫這么多吧,下邊還有視圖,存儲過程,事物等等,以后慢慢寫吧,也算一個溫故而知新的過程。