譚毓銀,李懷成,繆為民
(海南大學(xué)計(jì)算機(jī)與網(wǎng)絡(luò)空間安全學(xué)院,???70228)
《數(shù)據(jù)庫(kù)系統(tǒng)概論》[1]是我校信息類(lèi)的專(zhuān)業(yè)必修課,其教學(xué)目標(biāo)是向?qū)W生介紹數(shù)據(jù)庫(kù)系統(tǒng)的基本概念及其構(gòu)成,使學(xué)生掌握基本的關(guān)系數(shù)據(jù)庫(kù)理論和典型關(guān)系數(shù)據(jù)語(yǔ)言SQL的編程。而關(guān)系代數(shù)運(yùn)算及SQL語(yǔ)句用法是本課的重點(diǎn)和難點(diǎn),SQL語(yǔ)句在實(shí)際的數(shù)據(jù)庫(kù)開(kāi)發(fā)運(yùn)用中較靈活,其理論基礎(chǔ)離不開(kāi)對(duì)關(guān)系代數(shù)運(yùn)算的理解[2-4]。
通過(guò)多年的教學(xué),發(fā)現(xiàn)本課程涉及大量的理論講解,教學(xué)基本采用教材所給的案例,每章節(jié)所舉例題不盡相同,往往是東一個(gè)西一個(gè),沒(méi)有緊密的連貫性,缺乏統(tǒng)一的教學(xué)項(xiàng)目和案例設(shè)計(jì),教學(xué)效果并不是很好,造成學(xué)員學(xué)習(xí)目的不明確,成就感不強(qiáng),消極對(duì)待數(shù)據(jù)庫(kù)原理知識(shí)和SQL語(yǔ)言的學(xué)習(xí)[5-7]。
在實(shí)驗(yàn)教學(xué)過(guò)程中,先以學(xué)生接觸較多的學(xué)生選修課程模型為依托,合理設(shè)計(jì)教學(xué)案例,輔以圖示分解教學(xué),幫助學(xué)生掌握關(guān)系代數(shù)的運(yùn)算,再講解SQL語(yǔ)句基本用法,最后通過(guò)在實(shí)驗(yàn)中用SQL語(yǔ)句來(lái)實(shí)現(xiàn)關(guān)系代數(shù)運(yùn)算,從而加深學(xué)生對(duì)SQL語(yǔ)句用法和關(guān)系代數(shù)運(yùn)算的理解,為數(shù)據(jù)庫(kù)查詢(xún)打下堅(jiān)實(shí)的基礎(chǔ)。
關(guān)系代數(shù)是一種抽象的查詢(xún)語(yǔ)言,它用對(duì)關(guān)系的運(yùn)算來(lái)表達(dá)查詢(xún),是處理關(guān)系數(shù)據(jù)庫(kù)的重要數(shù)學(xué)基礎(chǔ),是關(guān)系數(shù)據(jù)操縱語(yǔ)言的一種傳統(tǒng)表達(dá)方式。
關(guān)系代數(shù)運(yùn)算按運(yùn)算符的不同可分為傳統(tǒng)的集合運(yùn)算和專(zhuān)門(mén)的關(guān)系運(yùn)算兩類(lèi)。傳統(tǒng)的集合運(yùn)算是二目運(yùn)算,包括并、差、交、笛卡爾積4種運(yùn)算;專(zhuān)門(mén)的關(guān)系運(yùn)算包括選擇、投影、連接、除運(yùn)算等[1]。
設(shè)有學(xué)生關(guān)系Stud、學(xué)生關(guān)系Other、課程關(guān)系Course和選修關(guān)系StudCous,如表1-表4所示。下面的關(guān)系代數(shù)運(yùn)算將對(duì)這四個(gè)關(guān)系進(jìn)行運(yùn)算。
表1 Stud關(guān)系
表2 Other關(guān)系
表3 Stud關(guān)系
表4 StudCous關(guān)系
設(shè)關(guān)系R和關(guān)系S具有相同的目n(即兩個(gè)關(guān)系都有n個(gè)屬性),且相應(yīng)的屬性取自同一個(gè)域,t是元組變量,t∈R表示t是R的一個(gè)元組。
(1)并運(yùn)算:將R與S合并,并且去掉重復(fù)元組后所構(gòu)成的一個(gè)關(guān)系。
例1:將Stud與Other合并成SU關(guān)系,關(guān)系代數(shù)運(yùn)算表達(dá)式為:
關(guān)系運(yùn)算的結(jié)果如表5所示。因?yàn)镺ther關(guān)系中的“714002”“714004”所對(duì)應(yīng)的元組已經(jīng)存在于Stud關(guān)系中,所以合并后的關(guān)系只保留了一份。
表5 并運(yùn)算后的SU關(guān)系
表6 交運(yùn)算后的SN關(guān)系
(2)交運(yùn)算:由既屬于R又屬于S的元組組成的新關(guān)系。
例2:將Stud與Other相交成SN關(guān)系,關(guān)系代數(shù)運(yùn)算表達(dá)式為:
關(guān)系運(yùn)算的結(jié)果如表6所示。因?yàn)镾tud及Other關(guān)系中都有“714002”“714004”所對(duì)應(yīng)的元組,所以相交后的關(guān)系只是由共同存在于這兩個(gè)關(guān)系的元組所組成的新關(guān)系。
(3)差運(yùn)算:由屬于R而不屬于S的所有元組組成,即在R中去掉R與S相同的元組。
例3:將Stud與Other進(jìn)行差運(yùn)算,關(guān)系代數(shù)運(yùn)算表達(dá)式為:
關(guān)系運(yùn)算的結(jié)果如表7所示。因?yàn)镾tud及Other關(guān)系中都有“714002”“714004”所對(duì)應(yīng)的元組,所以差運(yùn)算就是在Stud關(guān)系中去掉這兩個(gè)相同元組后所組成的新關(guān)系。
表7 差運(yùn)算后的SM關(guān)系
(4)笛卡爾積
這里的笛卡爾積嚴(yán)格地講應(yīng)該是廣義的笛卡爾積。設(shè)有n元關(guān)系R及m元關(guān)系S,它們分別有p、q個(gè)元組,則關(guān)系R與S經(jīng)笛卡爾積記為R×S,該關(guān)系是一個(gè)n+m元關(guān)系,元組個(gè)數(shù)是p×q,由R與S的有序組組合而成。即用R中的每個(gè)元組分別與S中的所有元組相結(jié)合組成一個(gè)新的關(guān)系。新的關(guān)系的屬性個(gè)數(shù)為R與S屬性個(gè)數(shù)之和,元組個(gè)數(shù)為R與S元組個(gè)數(shù)相乘積。
例4:將Stud與StudCous進(jìn)行笛卡爾積運(yùn)算,關(guān)系代數(shù)運(yùn)算表達(dá)式為:
關(guān)系運(yùn)算的結(jié)果如表8所示。
從表8中,可以看出,笛卡爾積實(shí)際上用左邊關(guān)系的每一行分別與右邊關(guān)系的所有行進(jìn)行相乘(或相合并)。注意:笛卡爾積的全集在應(yīng)用中是沒(méi)有意義的。這里列出全集只是表示全部可能的組合而已,并不代表實(shí)際上有這么多可行的組合。笛卡爾積運(yùn)算是為后面的連接、自然連接等做準(zhǔn)備。
表8 笛卡爾積后的SCP關(guān)系
(1)選擇:它是由關(guān)系R中滿(mǎn)足邏輯條件的元組所組成的新的關(guān)系,記作:
邏輯條件F表示選擇條件,它是一個(gè)邏輯表達(dá)式,取邏輯值“true”或“false”。
例5:查詢(xún)關(guān)系Stud中Dept為“計(jì)算機(jī)科學(xué)”的信息。
結(jié)果如表9所示。Stud關(guān)系原來(lái)有5個(gè)元組,而執(zhí)行邏輯條件Dept=“計(jì)算機(jī)科學(xué)”運(yùn)算后,只有2個(gè)元組滿(mǎn)足條件。講到這里,大家發(fā)現(xiàn),選擇運(yùn)算是對(duì)關(guān)系進(jìn)行元組(行)的選取,當(dāng)然,如果有重復(fù)的行,還需要?jiǎng)h除重復(fù)行后形成新的關(guān)系。
表9 選擇運(yùn)算后的關(guān)系
(2)投影:它是從R中選取出若干屬性列,去掉重復(fù)的元組所組成新的關(guān)系,記作:
例6:查詢(xún)關(guān)系Stud中Dept的信息。
關(guān)系代數(shù)運(yùn)算式為:∏Dept( S tud)
結(jié)果如表10所示。R關(guān)系原來(lái)有5個(gè)元組,而投影結(jié)果消除了重復(fù)的部分元組,因此只有3個(gè)元組。講到這里,大家發(fā)現(xiàn),投影不僅取消了原關(guān)系中的某些列,而且還可能消去了某些元組,因?yàn)槿∠四承傩粤泻?,就可能出現(xiàn)重復(fù)行,就取消這些完全相同的行。所以投影是能夠把一個(gè)關(guān)系的屬性域變小的運(yùn)算。
表10 投影運(yùn)算后的關(guān)系
所以,有了投影、選擇運(yùn)算,我們就可以方便地找到一個(gè)關(guān)系內(nèi)的任意行、列的數(shù)據(jù)。
(3)連接:它是從關(guān)系R和關(guān)系S的笛卡爾積中選取屬性間滿(mǎn)足一定條件的元組。記作:
其中,A和B分別為R和S上列數(shù)相等且可比的屬性組,θ是比較運(yùn)算符。因此,連接也稱(chēng)為θ連接。當(dāng)θ為“=”時(shí)的連接運(yùn)算稱(chēng)為等值連接,可以記為:
例7:查詢(xún)每個(gè)學(xué)生及其選修課程的情況。關(guān)系Stud與關(guān)系StudCous進(jìn)行Sno=S sn o的等值連接。關(guān)系代數(shù)運(yùn)算式為:SW=StudSno=Ssno StudCous
結(jié)果如表11所示。該關(guān)系實(shí)際上是在表8關(guān)系中進(jìn)行邏輯條件為“Sno=S sn o”的選擇運(yùn)算后得到的新關(guān)系,該運(yùn)算大大減少了元組的個(gè)數(shù)。但是請(qǐng)大家注意Sno和S sn o屬性對(duì)應(yīng)的值是一樣的。假如我們把S sno屬性名改為Sno,就將會(huì)變成自然連接。
表11 等值連接后的SW關(guān)系
(4)自然連接:自然連接是一種特殊的等值連接。它要求:①兩個(gè)關(guān)系要有公共的屬性域;②通過(guò)公共域的相等值進(jìn)行連接。記作:
例8:假設(shè)我們將關(guān)系StudCous中的S sn o屬性改名為Sno,把關(guān)系Stud與改名后的關(guān)系StudCous進(jìn)行自然連接。
關(guān)系代數(shù)運(yùn)算式為:SP=Stud?StudCous
結(jié)果如表12所示。該關(guān)系和表11的關(guān)系很類(lèi)似,只是少了Sno(S sn o已經(jīng)更名為Sno)的同名屬性列。即自然連接是在等值連接的基礎(chǔ)上,消除兩個(gè)關(guān)系的公共屬性域的連接。
表12 自然連接后的SP關(guān)系
一般的連接操作是從行的角度進(jìn)行運(yùn)算,但自然連接還需要取消重復(fù)列,所以是同時(shí)從行和列的角度進(jìn)行運(yùn)算。
(5)除運(yùn)算
設(shè)關(guān)系R除以關(guān)系S的結(jié)果為T(mén),則T包含所有在R但不在S中的屬性及其值,且T的元組與S的元組的所有組合都在R中。記作:
這個(gè)定義是教材給出的。在這幾種運(yùn)算中,除法運(yùn)算復(fù)雜、抽象,是教學(xué)環(huán)節(jié)中的難點(diǎn)問(wèn)題,學(xué)生理解起來(lái)比較困難[8]。如何來(lái)講解除法運(yùn)算呢?
我們先對(duì)StudCous關(guān)系的S sn o和Cno屬性做投影操作,即:SCNO=∏Ssno,Ccno(StudCous),得到的關(guān)系SCNO如表13所示。再對(duì)Course關(guān)系的Cno屬性做投影操作,即:CNO=∏Cno(Course),得到的關(guān)系CNO如表14所示。那么SCNO÷CNO得到的關(guān)系SSNO如表15所示。這實(shí)際上就是:
表13 SCNO關(guān)系
表14 CNO關(guān)系
表15 SSNO關(guān)系
例9:查詢(xún)選修了所有課程的學(xué)生姓名。
SQL(Structured Query Language)是關(guān)系數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)語(yǔ)言,也是一個(gè)通用的、功能極強(qiáng)的關(guān)系數(shù)據(jù)庫(kù)語(yǔ)言。其主要特點(diǎn)包括:綜合統(tǒng)一、高度非過(guò)程化、面向集合的操作方式、以同一種語(yǔ)法結(jié)構(gòu)提供多種使用方式、語(yǔ)言簡(jiǎn)潔、易學(xué)易用等。
數(shù)據(jù)查詢(xún)是數(shù)據(jù)庫(kù)的核心操作。SQL提供了SELECT語(yǔ)句進(jìn)行數(shù)據(jù)查詢(xún),該語(yǔ)句具有靈活的使用方式和豐富的功能[10]。其一般格式為:
基本的工作原理:FROM子句先被執(zhí)行,通過(guò)FROM子句獲得一個(gè)虛擬表,然后通過(guò)WHERE子句從虛擬表中獲取滿(mǎn)足條件的記錄,生成新的虛擬表。將新虛擬表中的記錄通過(guò)GROUP BY子句分組后得到更新的虛擬表,而后HAVING子句在最新的虛擬表中篩選出滿(mǎn)足條件的記錄組成另外一個(gè)虛擬表中,SELECT子句會(huì)將指定的列提取出來(lái)組成更新的虛擬表,最后ORDER BY子句對(duì)其進(jìn)行排序得出最終的虛擬表。通常這個(gè)最終的虛擬表被稱(chēng)為查詢(xún)結(jié)果集[11]。
每種關(guān)系運(yùn)算在SQL中都有對(duì)應(yīng)的實(shí)現(xiàn),Union、Intersect、Except分別對(duì)應(yīng)集合運(yùn)算中的并、交、差運(yùn)算,但在SQL Server中不支持Intersect、Except運(yùn)算符的使用。本實(shí)驗(yàn)通過(guò)在SQL Server 2008環(huán)境下實(shí)現(xiàn)關(guān)系代數(shù)的各種運(yùn)算(例1-例9),使學(xué)生在感性上進(jìn)一步認(rèn)識(shí)關(guān)系代數(shù)在數(shù)據(jù)庫(kù)中的應(yīng)用,從而更深刻地理解了關(guān)系代數(shù)運(yùn)算和更熟練地掌握了SQL語(yǔ)句的用法[12]。
例1中并運(yùn)算的SQL語(yǔ)句
Select*from Stud Union Select*from Other
例2中交運(yùn)算的SQL語(yǔ)句
Select Stud.*from Stud,Other Where Other.Sno=Stud.Sno)
例3中差運(yùn)算的SQL語(yǔ)句
Select*from Stud Where Sno not in(Select Sno from Other)
例4中笛卡爾積運(yùn)算的SQL語(yǔ)句
Select*from Stud,StudCous
例5中選擇運(yùn)算的SQL語(yǔ)句
Select*from Stud Where Dept=^'計(jì)算機(jī)科學(xué)'例6中投影運(yùn)算的SQL語(yǔ)句
Select Distinct Dept from Stud
例7中等值連接運(yùn)算的SQL語(yǔ)句
Select*from Stud,StudCous Where Stud.Sno=Stud?Cous.Ssno
例8中自然連接運(yùn)算的SQL語(yǔ)句
Select*from Stud,StudCous Where Stud.Sno=Stud?Cous.Sno
例9的SQL語(yǔ)句,除運(yùn)算
Select Sname From Stud Where not exists
(Select*From Course Where not exists
(Select*From StudCous Where Stud.Sno=StudCous.Ssno
And Course.Cno=StudCous.Ccno
)
)
注意,在做連接查詢(xún)時(shí),至少涉及兩個(gè)以上的表,用到的關(guān)系運(yùn)算為笛卡爾積或連接或自然連接。但它們都是在笛卡爾積的基礎(chǔ)上所進(jìn)行的操作。
最后,我們利用教材中的一個(gè)例子,引導(dǎo)學(xué)生思考查詢(xún)優(yōu)化的步驟,激發(fā)學(xué)生對(duì)查詢(xún)優(yōu)化的興趣。
例3.51查詢(xún)選修了95203的課程且成績(jī)?cè)?0分以上的所有學(xué)生的學(xué)號(hào)和姓名。
Select Stud.Sno,Stud.Sname From Stud,StudCous
Where Stud.Sno=StudCous.Ssno and StudCous.Score>=80
對(duì)應(yīng)的關(guān)系代數(shù)運(yùn)算表達(dá)式為:
從這個(gè)表達(dá)式中,先是關(guān)系Stud與StudCous做笛卡爾積運(yùn)算,然后再選取滿(mǎn)足邏輯條件為σCcno=95203∧Score≥80的元組組成一個(gè)虛擬表關(guān)系,再對(duì)該關(guān)系的Sno,Sname列進(jìn)行投影運(yùn)算,如果有重復(fù)行,去掉重復(fù)行后組成查詢(xún)結(jié)果集。在課堂講解上,就用表8笛卡爾積運(yùn)算的結(jié)果來(lái)演示,讓學(xué)生知道會(huì)產(chǎn)生大量的元組及屬性,然后引出優(yōu)化的問(wèn)題。
該查詢(xún)優(yōu)化的思想是先從StudCous中選取出σCcno=95203∧Score≥80的元組形成一個(gè)虛擬表關(guān)系,再和Stud中滿(mǎn)足連接條件的元組進(jìn)行連接得到最終的結(jié)果關(guān)系。
由此,一步步引導(dǎo)學(xué)生進(jìn)行查詢(xún)優(yōu)化的提出,在加強(qiáng)學(xué)生關(guān)系代數(shù)的學(xué)習(xí)的同時(shí),也為后續(xù)學(xué)生學(xué)習(xí)SQL查詢(xún)優(yōu)化指引了一個(gè)方向。
關(guān)系代數(shù)運(yùn)算是數(shù)據(jù)庫(kù)原理課中較為抽象的內(nèi)容,是SQL查詢(xún)的理論基礎(chǔ)。如果以純理論教學(xué)為主,學(xué)生不能真正理解關(guān)系代數(shù)運(yùn)算,也就不可能寫(xiě)出優(yōu)異的SQL語(yǔ)句。這就要求教師在設(shè)計(jì)教學(xué)案例時(shí),能夠縱覽全局,設(shè)計(jì)前后統(tǒng)一、連貫性強(qiáng)的教學(xué)項(xiàng)目案例,將能幫助學(xué)生快速理解該知識(shí)點(diǎn)乃至該門(mén)課程起到至關(guān)重要的作用,同時(shí)也能提高學(xué)生的實(shí)驗(yàn)動(dòng)手能力。由于該課程在近幾年中一直是我校的教學(xué)示范課程,2018年3月該課程成為“第二批海南省高校精品在線(xiàn)開(kāi)放課程立項(xiàng)建設(shè)課程”。