文/向沖 陳誠(chéng)
SQL語(yǔ)言是目前數(shù)據(jù)庫(kù)領(lǐng)域中非常實(shí)用、流行的主流語(yǔ)言。SQL是Structure Query Language的英文縮寫(xiě),意思是結(jié)構(gòu)化查詢(xún)語(yǔ)言。包括:數(shù)據(jù)查詢(xún) (SQL)、數(shù)據(jù)操縱 (DML)、數(shù)據(jù)定義 (DDL)和數(shù)據(jù)控制 (DCL)等功能于一體。數(shù)據(jù)查詢(xún)是數(shù)據(jù)庫(kù)的核心內(nèi)容,也是我們最常用的操作。數(shù)據(jù)查詢(xún)是通過(guò)SQL語(yǔ)句來(lái)實(shí)現(xiàn)的,利用SQL語(yǔ)句可以從數(shù)據(jù)庫(kù)中查詢(xún)出我們所需要的各種數(shù)據(jù)。[1]
數(shù)據(jù)查詢(xún)分為單表查詢(xún)和多表查詢(xún)。單表查詢(xún)是對(duì)一個(gè)表的查詢(xún),因?yàn)楸容^簡(jiǎn)單,這里不再說(shuō)明。多表查詢(xún)是對(duì)多個(gè)表,將分布在不同表中的數(shù)據(jù)根據(jù)需要進(jìn)行查詢(xún)。多表查詢(xún)可以通過(guò)連接查詢(xún)和嵌套查詢(xún)來(lái)實(shí)現(xiàn)。[2]下面以學(xué)生管理數(shù)據(jù)庫(kù)為例,介紹以上兩種查詢(xún)。其中學(xué)生表和成績(jī)表的關(guān)系模式如下:學(xué)生 (學(xué)號(hào),姓名,性別,出生日期,籍貫,班級(jí)代碼);成績(jī) (學(xué)號(hào),課程號(hào),成績(jī))。
1.1.1 定義。根據(jù)各個(gè)表之間的邏輯關(guān)系從兩個(gè)或多個(gè)表中查詢(xún)數(shù)據(jù)。如:查詢(xún)學(xué)生的學(xué)號(hào)、姓名、課程名稱(chēng)和成績(jī),涉及到的數(shù)據(jù)表有學(xué)生、課程和成績(jī)。
1.2.1 內(nèi)連接。內(nèi)連接 (inner join)是一種最常用的連接類(lèi)型。內(nèi)連接是一種任意條件的查詢(xún),如果兩個(gè)表的相關(guān)字段滿(mǎn)足連接條件,就從這兩個(gè)表中提取數(shù)據(jù)并組合成新的記錄,也就是在內(nèi)連接查詢(xún)中,只有滿(mǎn)足條件的元組才能出現(xiàn)在結(jié)果關(guān)系中。[3]
例如:要查詢(xún)每個(gè)已經(jīng)選課的學(xué)生的情況,查詢(xún)語(yǔ)句為:
SELECT*FROM學(xué)生INNER JOIN成績(jī)ON學(xué)生.學(xué)號(hào)=成績(jī).學(xué)號(hào)
連接查詢(xún)根據(jù)比較方式分為:
1.2.1.1 等值連接:使用等號(hào) (=)運(yùn)算符比較被連接的列的列值,稱(chēng)為等值連接。
1.2.1.2 不等連接:使用除等于運(yùn)算符以外的其它比較運(yùn)算符比較被連接的列的列值,稱(chēng)為不等連接。包括>、>=、<=、<、!>、!<和<>等運(yùn)算符。
1.2.1.3 自然連接:使用等于 (=)運(yùn)算符比較被連接列的列值,但刪除連接表中的重復(fù)列,稱(chēng)為自然連接。它屬于等值連接的一種特殊情況。
1.2.2 外連接。外連接是指將不滿(mǎn)足限制條件的表中的數(shù)據(jù)也顯示在最終結(jié)果中。
根據(jù)限制表的不同,外連接分為三種情況:
1.2.2.1 左外連接 (LEFTOUTER JOIN)
左外連接是限制連接條件右邊的表中的數(shù)據(jù)必須滿(mǎn)足連接條件,而不關(guān)左邊的表中的數(shù)據(jù)是否滿(mǎn)足連接條件,均輸出左邊表中的內(nèi)容。
例如:要查詢(xún)所有學(xué)生的選課情況,包括已經(jīng)選課的和還沒(méi)有選課的學(xué)生,查詢(xún)語(yǔ)句為:
SELECT學(xué)生.學(xué)號(hào),姓名,班級(jí)代碼,課程號(hào),成績(jī)
FROM學(xué)生LEFT OUTER JOIN成績(jī)ON學(xué)生.學(xué)號(hào)=成績(jī).學(xué)號(hào)
左外連接查詢(xún)中左邊表中的所有元組的信息都得到了保留。
1.2.2.2 右外連接 (RIGHTOUTERJOIN)。右外連接與左外連接類(lèi)似,只是右端表中的所有元組都列出,限制左端表的數(shù)據(jù)必須滿(mǎn)足連接條件,而不管右端表中的數(shù)據(jù)是否滿(mǎn)足連接條件,均輸出表中的內(nèi)容。
例如:同上例內(nèi)容,查詢(xún)語(yǔ)句為
SELECT學(xué)生.學(xué)號(hào),姓名,班級(jí)代碼,課程號(hào),成績(jī)
FROM學(xué)生RIGHTOUTERJOIN成績(jī)ON學(xué)生.學(xué)號(hào)=成績(jī).學(xué)號(hào)
右外連接查詢(xún)中右邊表中的所有元組的信息都得到了保留。
1.2.2.3 全外連接 (FULL OUTER JOIN)。全外連接查詢(xún)的特點(diǎn)是左、右兩端表中的元組都輸出,如果沒(méi)能找到匹配的元組,就使用NULL來(lái)代替。
例如:同左外連接例子內(nèi)容,查詢(xún)語(yǔ)句為:
SELECT學(xué)生.學(xué)號(hào),姓名,班級(jí)代碼,課程號(hào),成績(jī)
FROM學(xué)生FULL OUTER JOIN成績(jī)ON學(xué)生.學(xué)號(hào)=成績(jī).學(xué)號(hào)
全外連接查詢(xún)中所有表中的元組信息都得到了保留。
1.2.3 自連接。在同一個(gè)表內(nèi)進(jìn)行自身連接,這種查詢(xún)稱(chēng)為自連接查詢(xún),自連接必須為表指定兩個(gè)別名。
例如:要求檢索出和劉鑫同班同學(xué)的信息,查詢(xún)語(yǔ)句為:
SELECT學(xué)生.*FROM學(xué)生JOIN學(xué)生AS學(xué)1 ON學(xué)生.班級(jí)代碼=學(xué)生1.班級(jí)代碼
WHERE學(xué)生1.姓名=‘劉鑫’and學(xué)生1.學(xué)號(hào)<>學(xué)生.學(xué)號(hào)
1.2.4 交叉連接。交叉連接即笛卡兒乘積,是指兩個(gè)關(guān)系中所有元組的任意組合。一般情況下,交叉查詢(xún)是沒(méi)有實(shí)際意義的。
例如:如果希望得到學(xué)生和成績(jī)兩個(gè)關(guān)系模式的乘積,查詢(xún)語(yǔ)句為:
2.1.1 定義。嵌套查詢(xún)是指在一個(gè)SELECT語(yǔ)句的WHERE子句中嵌套另一條SELECT語(yǔ)句的查詢(xún),又稱(chēng)為子查詢(xún)。
2.2.1 無(wú)關(guān)子查詢(xún)。無(wú)關(guān)子查詢(xún)的執(zhí)行不依賴(lài)于外部嵌套。查詢(xún)的執(zhí)行過(guò)程為:首先執(zhí)行子查詢(xún),子查詢(xún)得到的結(jié)果作為外部查詢(xún)的條件使用,然后執(zhí)行外部查詢(xún)。通常使用比較運(yùn)算符或[NOT]IN關(guān)鍵字。
2.2.1.1 返回一個(gè)值的子查詢(xún)。子查詢(xún)的返回值只有一個(gè)時(shí),可以使用比較運(yùn)算符如=、<、>、>=、<=、!=等將父查詢(xún)和子查詢(xún)連接起來(lái)。
例如:要求檢索出和劉鑫同班同學(xué)的信息,查詢(xún)語(yǔ)句為:
SELECT*FROM學(xué)生WHERE班級(jí)代碼=(SELECT班級(jí)代碼FROM學(xué)生 WHERE姓名=’劉鑫’)AND姓名<>’劉鑫’
2.2.1.2 返回一組值的子查詢(xún)。子查詢(xún)的返回值不止一個(gè),而是一個(gè)集合時(shí),可以在比較運(yùn)算符和子查詢(xún)之間插入ANY、SOME或ALL關(guān)鍵字。其中等值關(guān)系可以使用IN關(guān)鍵字。
例如:查詢(xún)成績(jī)高于選修了“計(jì)算機(jī)基礎(chǔ)”課程平均成績(jī)的學(xué)生的學(xué)號(hào)和姓名。
SELECT 學(xué)生.學(xué)號(hào),學(xué)生.姓名FROM 成績(jī)JOIN 學(xué)生ON 學(xué)生.學(xué)號(hào)=成績(jī).學(xué)號(hào)
JOIN課程 ON成績(jī).課程號(hào)=課程.課程號(hào)WHERE課程名= '計(jì)算機(jī)基礎(chǔ)'AND
成績(jī) >ANY(SELECT avg(成績(jī))FROM成績(jī),課程WHERE 成績(jī).課程號(hào)=課程.課程號(hào)and課程名=‘計(jì)算機(jī)基礎(chǔ)’)
2.2.2 相關(guān)子查詢(xún)。相關(guān)子查詢(xún)是指在子查詢(xún)中,子查詢(xún)的查詢(xún)條件中引用了外層查詢(xún)表中的值。執(zhí)行時(shí)先執(zhí)行外部查詢(xún)語(yǔ)句,然后根據(jù)外部查詢(xún)返回的結(jié)果執(zhí)行內(nèi)部查詢(xún)語(yǔ)句。通常使用[NOT]EXISTS關(guān)鍵字。
例如:查詢(xún)沒(méi)有學(xué)習(xí)任何課程的學(xué)生的學(xué)號(hào)和姓名。
SELECT學(xué)號(hào),姓名FROM學(xué)生WHERE NOT EXISTS(SELECT*FROM成績(jī)WHERE成績(jī).學(xué)號(hào)=學(xué)生.學(xué)號(hào))
從“要求檢索出和劉鑫同班同學(xué)的信息”這個(gè)例子中我們可以看到,使用連接查詢(xún)和嵌套查詢(xún)實(shí)現(xiàn)該查詢(xún)的結(jié)果完全相同。由此我們可以得出這樣一個(gè)結(jié)論:連接查詢(xún)和嵌套查詢(xún)之間有時(shí)是可以相互替換的,但不是所有情況下都可以互換。下面將分別介紹連接查詢(xún)和嵌套查詢(xún)的優(yōu)劣。
3.1 連接查詢(xún)的優(yōu)勢(shì)和劣勢(shì)。連接查詢(xún)使用簡(jiǎn)單,但因?yàn)樵诟鞅磉B接的同時(shí)對(duì)所有的條件綜合查詢(xún),所以不易發(fā)現(xiàn)錯(cuò)誤,一旦出錯(cuò),糾錯(cuò)也比較麻煩。另外,連接查詢(xún)實(shí)際上是將所有表根據(jù)條件先合并成一個(gè)表。因此在數(shù)據(jù)量很大的情況下,對(duì)計(jì)算機(jī)系統(tǒng)的要求較高,需占用更多的系統(tǒng)資源。
3.2 嵌套查詢(xún)的優(yōu)勢(shì)和劣勢(shì)。嵌套查詢(xún)是用戶(hù)必須清楚每一個(gè)子查詢(xún)的結(jié)果及各表之間的邏輯關(guān)系,對(duì)用戶(hù)要求較高。但嵌套查詢(xún)是逐步求解,需要的計(jì)算機(jī)系統(tǒng)開(kāi)銷(xiāo)較小。
3.3 怎樣合理運(yùn)用連接查詢(xún)和嵌套查詢(xún)。綜上可以看出,連接查詢(xún)和嵌套查詢(xún)各自有其優(yōu)勢(shì)和劣勢(shì),在實(shí)際查詢(xún)過(guò)程中到底采用哪種查詢(xún)方式,因根據(jù)使用習(xí)慣及對(duì)兩種查詢(xún)方式的熟練程度確定,也可以混合使用。
綜上所述,查詢(xún)的優(yōu)化必須符合以下條件:滿(mǎn)足查詢(xún)需求的同時(shí)提高查詢(xún)速度,并能減少計(jì)算機(jī)系統(tǒng)開(kāi)銷(xiāo)為原則。熟練掌握SQL查詢(xún)功能及技巧是基礎(chǔ),另外了解每種查詢(xún)的優(yōu)劣才能更好的選擇合適的查詢(xún)方式。筆者首先介紹了連接查詢(xún)和嵌套查詢(xún)的定義和分類(lèi),然后通過(guò)兩者的對(duì)比分析,比較了兩者的優(yōu)勢(shì)和劣勢(shì),總結(jié)出實(shí)際使用過(guò)程中可根據(jù)自身的實(shí)際需求和使用習(xí)慣選擇合適的查詢(xún)方式。
[1]王良元,SQ連接、嵌套與混合查詢(xún) [J],電腦學(xué)習(xí),2005
[2]張文雯,SQ嵌套查詢(xún) [J],信息技術(shù),2011
[3]雷琳,SQL查詢(xún)語(yǔ)句優(yōu)化的研究[J],武漢船舶職業(yè)技術(shù)學(xué)院,2011