版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第4章關(guān)系數(shù)據(jù)庫標(biāo)準(zhǔn)語言SQL4.1SQL語言概述4.2網(wǎng)上書店數(shù)據(jù)庫 4.3數(shù)據(jù)定義功能4.4SQL數(shù)據(jù)更新功能4.5SQL數(shù)據(jù)查詢功能4.6SQL數(shù)據(jù)控制功能4.7視圖4.8嵌入式SQL本章小結(jié)習(xí)題4
本章主要內(nèi)容
由于SQL語言的標(biāo)準(zhǔn)化,所以大多數(shù)關(guān)系型數(shù)據(jù)庫系統(tǒng)都支持SQL語言。SQL語言已經(jīng)發(fā)展成為多種平臺(tái)進(jìn)行交互操作的底層會(huì)話語言,成為數(shù)據(jù)庫領(lǐng)域中一個(gè)主流語言。這一章將詳細(xì)介紹SQL的核心部分:數(shù)據(jù)定義、數(shù)據(jù)更新、數(shù)據(jù)查詢、數(shù)據(jù)控制、視圖和嵌入式SQL等。
本章學(xué)習(xí)目標(biāo)
—
熟練掌握SQL語言的數(shù)據(jù)定義、數(shù)據(jù)查詢、數(shù)據(jù)更新功能。
—
掌握SQL語言的數(shù)據(jù)控制功能。
—
掌握SQL語言的視圖操作。
—
了解嵌入式SQL的應(yīng)用及使用方法。
4.1SQL語言概述
SQL是介于關(guān)系代數(shù)與關(guān)系演算之間的一種結(jié)構(gòu)化查詢語言,其功能不僅僅是查詢。SQL是一個(gè)功能強(qiáng)大,通用的、簡(jiǎn)單易學(xué)的數(shù)據(jù)庫語言。
4.1.1SQL語言功能特征
1.綜合統(tǒng)一
SQL的綜合統(tǒng)一表現(xiàn)為DDL、DML、DCL的統(tǒng)一。SQL語言將數(shù)據(jù)定義語言DDL、數(shù)據(jù)操縱語言DML、數(shù)據(jù)控制語言DCL功能集于一體,語言風(fēng)格統(tǒng)一,可以獨(dú)立完成數(shù)據(jù)庫生命周期中的全部活動(dòng)。
2.高度非過程化
SQL語言進(jìn)行數(shù)據(jù)操作時(shí),只需要提出“做什么”,而不需說明“怎么做”,因此無需了解存取路徑及路徑的選擇,并且SQL語言的操作過程也是由系統(tǒng)自動(dòng)完成的,這樣減輕了用戶的負(fù)擔(dān),有利于提高數(shù)據(jù)的獨(dú)立性。
3.面向集合的操作方式
SQL語言采用集合的操作方式,不僅操作的對(duì)象、操作的結(jié)果可以是集合,而且一次插入、刪除、更新操作的對(duì)象也可以是集合,即SQL語言既可以接受集合作為輸入,也可以返回集合作為輸出。
4.一種語法,兩種使用方式
SQL語言既是自含式語言,又是嵌入式語言。作為自含式語言,SQL可以獨(dú)立地用于聯(lián)機(jī)交互操作,用戶可以在鍵盤上直接輸入命令對(duì)數(shù)據(jù)庫進(jìn)行操作;作為嵌入式語言,SQL語言可以嵌入到高級(jí)語言的程序中去,如C、Java等。在兩種不同的使用方式下,SQL的語法結(jié)構(gòu)基本一致,為應(yīng)用程序的研發(fā)帶來了很大的靈活性和方便性。
5.語言簡(jiǎn)潔,易學(xué)易用
SQL語言功能極為強(qiáng)大,但語言結(jié)構(gòu)簡(jiǎn)捷,設(shè)計(jì)構(gòu)思非常巧妙。在SQL語言中所有的核心功能只需要9個(gè)動(dòng)詞,如表4.1所示,而且語句接近英語語句,方便學(xué)習(xí),容易使用。
4.1.2SQL語言基本概念
SQL語言支持?jǐn)?shù)據(jù)庫三級(jí)模式結(jié)構(gòu),如圖4.1所示,其中外模式(E)對(duì)應(yīng)于視圖(View)和部分基本表;模式(C)對(duì)應(yīng)于基本表,是數(shù)據(jù)庫中全體數(shù)據(jù)的邏輯結(jié)構(gòu)和特征的描述,是所有用戶的公共數(shù)據(jù)視圖;內(nèi)模式(I)對(duì)應(yīng)于存儲(chǔ)文件。
圖4.1SQL支持關(guān)系數(shù)據(jù)庫三級(jí)模式結(jié)構(gòu)
基本表是本身獨(dú)立存在的表,在SQL中一個(gè)關(guān)系就對(duì)應(yīng)一個(gè)基本表。一個(gè)(或多個(gè))基本表對(duì)應(yīng)一個(gè)存儲(chǔ)文件,一個(gè)表可以帶若干索引,索引也存放在存儲(chǔ)文件中。存儲(chǔ)文件的邏輯結(jié)構(gòu)組成了關(guān)系數(shù)據(jù)庫的內(nèi)模式,物理結(jié)構(gòu)是任意的,對(duì)用戶透明。
視圖是從一個(gè)或幾個(gè)基本表中導(dǎo)出的表。數(shù)據(jù)庫中只存放視圖的定義而不存放視圖對(duì)應(yīng)的數(shù)據(jù),這些數(shù)據(jù)仍然存放在導(dǎo)出視圖的基本表中,因此視圖是一個(gè)虛表。在概念上視圖與基本表等同,用戶可以在視圖上再定義視圖。
4.2網(wǎng)上書店數(shù)據(jù)庫
用網(wǎng)上書店數(shù)據(jù)庫作為一個(gè)例子來講解SQL的數(shù)據(jù)定義、數(shù)據(jù)操縱、數(shù)據(jù)查詢和數(shù)據(jù)控制語句的具體應(yīng)用。為此,定義網(wǎng)上書店數(shù)據(jù)庫,它包括5個(gè)表,具體的定義見4.3.1節(jié)中例4.1和例4.2,關(guān)系的主碼加下畫線表示。
用戶表:USER1(ID,NAME,PASSWORD,ADDRESS,POSTCODE,EMAIL,HOMEPHONE,CELLPHONE,OFFICEPHONE);
圖書類型表:SORTKIND(ID,NAME);
圖書表:PRODUCT(ID,NAME,DESCRIPTION,PRICE,IMG,ZUOZHE,SORTKIND_ID);
訂單表:USER1_ORDER(ID,STATUS,COST,DATE,USER1_ID);
訂單條目表:ORDER_ITERM(ID,AMOUNT,PRODUCT_ID,ORDER_ID)。
4.3數(shù)據(jù)定義功能
SQL數(shù)據(jù)定義功能主要有數(shù)據(jù)庫模式的定義、基本表的定義、視圖的定義以及索引的定義四部分。特別要注意的是這里所說的“定義”不僅僅是對(duì)象的創(chuàng)建(CREATE),還包括刪除(DROP)和修改(ALTER),共三部分內(nèi)容。
4.3.1基本表的操作
在關(guān)系數(shù)據(jù)庫中,關(guān)系是數(shù)據(jù)庫的基本組成單位,關(guān)系又稱為表。建立數(shù)據(jù)庫的重要一步就是建立基本表,本節(jié)主要討論基本表的定義。
1.基本表的創(chuàng)建
在SQL語言中,使用CREATETABLE語句創(chuàng)建基本表,其一般格式如下:
CREATETABLE<基本表名>(<列名><數(shù)據(jù)類型>[列級(jí)完整性約束條件]
[,<列名><數(shù)據(jù)類型>[列級(jí)完整性約束條件]]…
[,<表級(jí)完整性約束條件>])
<基本表名>是所要定義的表名,它可以有一個(gè)或多個(gè)屬性(列)。
建表的同時(shí)還可以定義該表的完整性約束條件。當(dāng)用戶操作基本表時(shí),DBMS自動(dòng)檢查該操作是否違反了預(yù)先定義的完整性約束條件。
說明:在SQL語句格式中,有下列約定符號(hào)和相應(yīng)的語法規(guī)定。
(1)語法格式的約定符號(hào)。
·<>:其中的內(nèi)容為必選項(xiàng),表示不能為空的實(shí)際語義。
·[]:其中的內(nèi)容為任選項(xiàng)。
·{}或|:必選其中的一項(xiàng)。
(2)語法規(guī)定。
一般語法規(guī)定:
·SQL中數(shù)據(jù)項(xiàng)(列項(xiàng)、表和視圖)的分隔符為“,”。
·字符串常數(shù)的定界符用單引號(hào)“‘”表示。
·SQL語句的結(jié)束符為“;”。
·SQL采用格式化書寫方式。
·SQL語句中的所有符號(hào)均為英文半角狀態(tài)下符號(hào)。
【例4.1】建立一個(gè)“用戶”表USER1,它由用戶編號(hào)ID、姓名NAME、密碼PASSWORD、地址ADDRESS、郵編POSTCODE、電子郵箱EMAIL、宅電HOMEPHONE、移動(dòng)電話CELLPHONE、辦公室電話OFFICEPHONE
9個(gè)屬性組成。其中用戶編號(hào)為主鍵,密碼和姓名不許為空。
系統(tǒng)執(zhí)行上面的CREATETABLE語句后,就在數(shù)據(jù)庫中建立一個(gè)新的空的“用戶”表USER1,并將有關(guān)表的定義及有關(guān)的約束條件存放在數(shù)據(jù)字典中。
定義基本表時(shí),要指明各屬性列的數(shù)據(jù)類型及長度,不同的數(shù)據(jù)庫系統(tǒng)支持的數(shù)據(jù)類型不完全相同,表4.2列舉了主要數(shù)據(jù)類型。
【例4.2】創(chuàng)建“圖書類型”表SORTKIND,它由類型號(hào)ID和類型名NAME組成,其中ID為主鍵。創(chuàng)建“圖書”表PRODUCT,它由圖書號(hào)ID、圖書名NAME、描述DESCRIPTION、單價(jià)PRICE、圖片IMG、作者ZUOZHE、圖書類型號(hào)SORTKIND_ID
7個(gè)屬性組成。其中圖書號(hào)為主鍵不能為空,SORTKIND_ID為外鍵。創(chuàng)建“訂單”表USER1_ORDER,它由訂單號(hào)ID、狀態(tài)STATUS、單價(jià)COST、日期DATE、用戶號(hào)USER1_ID組成,其中訂單號(hào)為主鍵,用戶號(hào)為外鍵。創(chuàng)建“訂單條目”表ORDER_ITERM,它由條目號(hào)ID、數(shù)量AMOUNT、圖書號(hào)PRODUCT_ID、訂單號(hào)ORDER_ID組成,其中條目號(hào)為主鍵,圖書號(hào)和訂單號(hào)是外鍵。
2.完整性約束
完整性約束的用途是限制輸入到基本表中的值的范圍,SQL的完整性約束可以分為列級(jí)完整性約束和表級(jí)完整性約束兩種。
列級(jí)完整性約束:針對(duì)關(guān)系屬性值設(shè)置的限定條件,只能應(yīng)用在一列上。
表級(jí)完整性約束:涉及關(guān)系中多個(gè)屬性的限制條件,可以應(yīng)用在一個(gè)基本表中的多個(gè)屬性列上。當(dāng)需要在一個(gè)基本表中的多個(gè)列上建立約束條件時(shí),只能建立表級(jí)約束。當(dāng)創(chuàng)建完整性約束之后,它作為基本表定義的一部分,被存入數(shù)據(jù)字典中。
(1)實(shí)體完整性約束(PRIMARYKEY約束)。實(shí)體完整性約束也稱為PRIMARYKEY約束,即主鍵約束。它能保證主鍵的唯一性和非空性。一個(gè)基本表的主鍵由若干屬性列組成,可能只含有一列,也可能有幾列。實(shí)體完整性約束可以在列級(jí)或表級(jí)上進(jìn)行定義,但不可以在兩個(gè)級(jí)別上同時(shí)定義。在創(chuàng)建基本表時(shí),PRIMARYKEY約束定義主鍵的方法如下:
①?PRIMARYKEY約束直接寫在列名及其類型之后。
②按照語法在相應(yīng)的列名及其類型后單獨(dú)列出:
CONSTRAINT<約束名>PRIMARYKEY;
其中,<約束名>是PRIMARYKEY約束的名字。
③在CREATETABLE語句列出基本表的所有的列定義之后,再附加一個(gè)PRIMARYKEY約束說明:
PRIMARYKEY(<列名1>[,<列名2>,…,N]);
注意:關(guān)系模型的實(shí)體完整性在CREATETABLE中用PRIMARYKEY定義。若單屬性構(gòu)成的主鍵可以有兩種說明方法:定義為列級(jí)約束條件或定義為表級(jí)約束條件。若對(duì)于多個(gè)屬性構(gòu)成的主鍵只有一種說明方法:定義為表級(jí)約束條件。
【例4.3】將USER1_ORDER表中的ID屬性定義為主鍵。
①在列級(jí)定義主鍵,定義語句如下:
②在表級(jí)定義主鍵,定義語句如下:
插入或?qū)χ麈I列進(jìn)行更新操作時(shí),RDBMS按照實(shí)體完整性規(guī)則自動(dòng)進(jìn)行檢查,檢查內(nèi)容包括:檢查主鍵值是否唯一,如果不唯一則拒絕插入或修改;檢查主鍵的各個(gè)屬性是否為空,只要有一個(gè)為空就拒絕插入或修改。檢查記錄中主鍵值是否唯一的方法是進(jìn)行全表掃描,如圖4.2所示。
圖4.2插入記錄時(shí)對(duì)全表的掃描
(2)參照完整性約束(FOREIGNKEY約束)。參照完整性約束也稱為FOREIGNKEY約束或外鍵約束,用于定義參照完整性,即用來維護(hù)兩個(gè)基本表之間的一致性關(guān)系。外鍵的建立主要是通過將一個(gè)基本表中的主鍵所在的列包含在另一個(gè)表中,而這些列就是另一個(gè)基本表的外鍵。
定義外鍵有三種方式,分別是:
①如果外鍵只有一個(gè)屬性列,可以在它的列名和類型后面直接用FOREIGNKEY說明它參照哪個(gè)表哪列,其語法格式為
REFERENCES<表名>(<列名>)
②
可在屬性列表后面增加一個(gè)或幾個(gè)外鍵說明,其語法格式為
FOREIGNKEY(<列名>)REFERENCES<表名>(<列名>)
③可在相應(yīng)列名及其類型后面單獨(dú)列出并指定約束名,其語法格式為
CONSTRAINT<約束名>FOREIGNKEY(<列名>)REFERENCES<表名>(<列名>)
【例4.4】定義ORDER_ITERM中的參照完整性。
參照完整性違約處理方法有三種:拒絕(NOACTION)執(zhí)行,它是默認(rèn)策略;級(jí)聯(lián)(CASCADE)操作;設(shè)置為空值(SET-NULL)。對(duì)于參照完整性,除了應(yīng)該定義外鍵,還應(yīng)定義外鍵列是否允許空值。
(3)用戶定義的完整性。用戶定義的完整性就是針對(duì)某一具體應(yīng)用的數(shù)據(jù)必須滿足的語義要求。用戶定義的完整性由RDBMS提供,而不必由應(yīng)用程序承擔(dān)屬性上的約束條件定義。
關(guān)系模型的自定義完整性定義在CREATETABLE語句中,包括列值非空(NOTNULL)、列值唯一(UNIQUE)、檢查列值是否滿足一個(gè)布爾表達(dá)式(CHECK)。
①不允許取空值(NOTNULL約束)。
【例4.5】在定義SORTKIND表時(shí),說明NAME屬性不允許取空值。
②列值唯一(UNIQUE約束)。UNIQUE約束是唯一性約束,主要用來確保不受PRIMARYKEY約束的列上的數(shù)據(jù)的唯一性。PRIMARYKEY約束與UNIQUE約束的區(qū)別主要表現(xiàn)在以下幾方面:
·UNIQUE約束,主要用在非主鍵的一列或多列上要求數(shù)據(jù)唯一的情況。
·UNIQUE約束,允許該列上存在NULL值,在主鍵決不允許出現(xiàn)這種情況。
·在一個(gè)基本表上可以設(shè)置多個(gè)UNIQUE約束,但只能有一個(gè)主鍵約束。
UNIQUE約束也可以在列級(jí)或表級(jí)上設(shè)置。如果要設(shè)置多個(gè)列的UNIQUE約束,則必須設(shè)置表級(jí)約束。在SQL語句中,創(chuàng)建基本表時(shí),定義UNIQUE約束的方法如下:
列級(jí)UNIQUE約束:
CONSTRAINT<約束名>UNIQUE
其中,<約束名>是UNIQUE約束的名字。
表級(jí)UNIQUE約束:
CONSTRAINT<約束名>UNIQUE(<列名1>[,<列名2>,…,N])
【例4.6】建立SORTKIND,要求類型名稱NAME列取值唯一,類型編號(hào)ID列為主鍵。
CREATETABLESORTKIND
(
IDVARCHAR(16)PRIMARYKEY,/*列級(jí)完整性約束條件,ID為主鍵*/
NAMEVARCHAR(32)CONSTRAINTUN_NAME
UNIQUE
);
③?CHECK約束。
【例4.7】在ORDER_ITERM表中,AMOUNT小于100。
【例4.8】在高校管理系統(tǒng)中創(chuàng)建一學(xué)生表,當(dāng)學(xué)生的性別是男時(shí),其名字不能以MS.開頭。
3.基本表的修改
隨著環(huán)境和需求的變化,有時(shí)需要修改已建好的基本表。表的修改包括結(jié)構(gòu)的修改和約束條件的修改。在SQL語言中,使用ALTERTABLE語句修改基本表,其一般格式如下:
ALTERTABLE<基本表名>
[ADD<新列名><數(shù)據(jù)類型>|[完整性約束]]
[DROP<完整性約束名>]
[ALTERCOLUMN<列名><數(shù)據(jù)類型>];
說明:
①<基本表名>是要修改的基本表的名字。
②ADD子句用于在基本表中增加新列和新完整性約束條件。新增加的列不能定義為“NOTNULL”,因?yàn)椴徽摶颈碇惺欠裼袛?shù)據(jù),新增加的列一律為空值(NULL)。
③DROP子句用于刪除完整性約束條件。
④ALTER子句用于修改原有的列定義,包括列名和列的數(shù)據(jù)類型及長度。
【例4.9】向USER1表中增加“性別”一列,其數(shù)據(jù)類型為字符型。
ALTERTABLEUSER1ADDSEXCHAR(2);
不論基本表中原來是否有數(shù)據(jù),新增加的列一律為空值。
【例4.10】將HOMEPHONE數(shù)據(jù)類型改為整型。
ALTERTABLEUSER1ALTERCOLUMNHOMEPHONEINT;
【例4.11】刪除用戶姓名必須取唯一值的約束。
ALTERTABLEUSER1DROPUNIQUE(NAME);
4.基本表的刪除
當(dāng)基本表不再需要時(shí),可以用DROPTABLE刪除表?;颈硪坏┍粍h除,其中的所有數(shù)據(jù)也會(huì)隨之丟失。
在SQL語言中,使用DROPTABLE刪除基本表,其一般格式如下:
DROPTABLE<基本表名>[RESTRICT|CASCADE];
RESTRICT:表明刪除表是有限制的。欲刪除的基本表不能被其他表的約束所引用,如果存在依賴該表的對(duì)象,則此表不能被刪除。
CASCADE:表明刪除該表沒有限制。在刪除基本表的同時(shí),相關(guān)的依賴對(duì)象一起刪除。
說明:
①<基本表名>是要?jiǎng)h除的基本表的名字。
②基本表被刪除后,依附于此表建立的索引和視圖都將被自動(dòng)刪除掉,并且無法恢復(fù),此時(shí)系統(tǒng)釋放其所占的存儲(chǔ)空間。因此執(zhí)行刪除基本表的操作一定要格外小心。
③只有基本表的擁有者才可以使用此語句。
④不能使用DROP刪除系統(tǒng)表。
【例4.12】刪除基本表PRODUCT。
DROPTABLEPRODUCT;
注意:不同的數(shù)據(jù)庫產(chǎn)品在遵循SQL標(biāo)準(zhǔn)的基礎(chǔ)上具體實(shí)現(xiàn)細(xì)節(jié)和處理策略上會(huì)與標(biāo)準(zhǔn)有差異。
表4.3就SQL-99標(biāo)準(zhǔn)對(duì)DROPTABLE的規(guī)定,對(duì)比分析KingbaseES、Oracle9I、MSSQLServer2000這三種數(shù)據(jù)庫產(chǎn)品對(duì)DROPTABLE的不同處理策略。
表中的R表示RESTRICT,即DROPTABLE<基本表名>RESTRICT;C表示CASCADE,即DROPTABLE<基本表名>CASCADE。其中Oracle9I沒有RESTRICT選項(xiàng);MSSQLServer2000沒有RESTRICT和CASCADE選項(xiàng)。
從比較中可以知道:
(1)對(duì)于索引,刪除基本表后,這3種RDBMS都自動(dòng)刪除該表上已經(jīng)建立的所有索引。
(2)對(duì)于視圖,Oracle9I與MSSQLServer2014都是刪除基本表后,還保留表上的視圖定義,但視圖已經(jīng)失效。KingbaseES分兩種情況:若刪除時(shí)帶RESTRIC選項(xiàng),則不可以刪除表;若帶CASCADE選項(xiàng)刪除,則可以刪除表,也可以同時(shí)刪除視圖。KingbaseES的這種策略符合SQL-99標(biāo)準(zhǔn)。
(3)對(duì)于存儲(chǔ)過程和函數(shù),刪除基本表后,這3種數(shù)據(jù)庫產(chǎn)品都不自動(dòng)刪除建立在此表基礎(chǔ)上的存儲(chǔ)過程和函數(shù),但這些存儲(chǔ)過程和函數(shù)卻已失效。
同樣對(duì)于其他的SQL語句,不同的數(shù)據(jù)庫產(chǎn)品在處理策略上會(huì)與標(biāo)準(zhǔn)SQL有所差異。因此,如果發(fā)現(xiàn)本書中的個(gè)別例子在某種數(shù)據(jù)庫產(chǎn)品中無法通過,請(qǐng)讀者參考相關(guān)數(shù)據(jù)庫產(chǎn)品手冊(cè)。
4.3.2索引操作
在使用數(shù)據(jù)庫系統(tǒng)時(shí),用戶所看到和操作的數(shù)據(jù)就好像是在簡(jiǎn)單的二維表中的,而實(shí)際上,對(duì)于數(shù)據(jù)在磁盤上是如何存儲(chǔ)的,用戶并不清楚。但是,數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu),卻是決定數(shù)據(jù)庫性能的主要因素。索引是最常見的改善數(shù)據(jù)庫性能的技術(shù)。
索引就是加快檢索表中數(shù)據(jù)的方法。數(shù)據(jù)庫的索引類似于書籍的索引。在書籍中,索引允許用戶不必翻閱整本書就能迅速地找到所需要的信息。在數(shù)據(jù)庫中,索引也允許數(shù)據(jù)庫程序迅速地找到表中的數(shù)據(jù),而不必掃描整個(gè)數(shù)據(jù)庫。
1.索引的特點(diǎn)
簡(jiǎn)單地說,一個(gè)索引就是一個(gè)指向表中數(shù)據(jù)的指針。例如,若讀者想找出一本書中討論某主題的所有頁碼,首先需要去查閱按字母順序列出的包含所有主題的索引,然后再去閱讀某些特定的頁。在數(shù)據(jù)庫中,索引具有同樣的作用。索引查詢指向基本表中數(shù)據(jù)的確切物理地址。實(shí)際上,查詢都被定向于數(shù)據(jù)庫中數(shù)據(jù)在數(shù)據(jù)文件中的地址,但對(duì)查詢者來說,它是在參閱一張表。
索引是在SQL基本表中列上建立的一種數(shù)據(jù)庫對(duì)象,也可稱其為索引文件,它和建立于其上的基本表是分開存儲(chǔ)的。建立索引的主要目的是提高數(shù)據(jù)檢索性能。索引可以被創(chuàng)建或撤銷,這對(duì)數(shù)據(jù)毫無影響。但是,一旦索引被撤銷,數(shù)據(jù)查詢的速度可能會(huì)變慢。索引要占用物理空間,且通常比基本表本身占用的空間還要大。
當(dāng)建立索引以后,它便記錄了表中被索引列的每一個(gè)取值。當(dāng)在表中加入新的數(shù)據(jù)時(shí),索引中也增加相應(yīng)的數(shù)據(jù)項(xiàng)。當(dāng)對(duì)數(shù)據(jù)庫中的基本表建立了索引并且進(jìn)行數(shù)據(jù)查詢時(shí),首先在相應(yīng)的索引中查找。如果數(shù)據(jù)被找到,則返回該數(shù)據(jù)在基本表中的確切位置。
對(duì)于一個(gè)基本表,可以根據(jù)應(yīng)用環(huán)境的需要?jiǎng)?chuàng)建若干索引以提供多種存取途徑。通常,索引的創(chuàng)建和撤銷由DBA或表的擁有者負(fù)責(zé)。用戶不能也不必要在存取數(shù)據(jù)時(shí)選擇索引,索引的選擇由系統(tǒng)自動(dòng)進(jìn)行。
2.索引的用途
索引的用途表現(xiàn)在三個(gè)方面:
(1)由于基本表中的列比較多(有的可達(dá)幾百列),元組也比較多(大的數(shù)據(jù)庫中的元組可達(dá)數(shù)萬個(gè)),因此數(shù)據(jù)文件會(huì)很大。在進(jìn)行數(shù)據(jù)查詢時(shí),如果不使用索引,則需要將數(shù)據(jù)文件分塊,逐個(gè)讀到內(nèi)存中,再進(jìn)行查找比較操作。而使用索引后,系統(tǒng)會(huì)先將索引文件讀入內(nèi)存,根據(jù)索引項(xiàng)找到元組的地址,然后再根據(jù)地址將元組數(shù)據(jù)讀入內(nèi)存。
(2)保證數(shù)據(jù)的唯一性。索引的定義中包括定義數(shù)據(jù)唯一性的內(nèi)容。當(dāng)定義了數(shù)據(jù)唯一性的功能后,再對(duì)相關(guān)的索引項(xiàng)進(jìn)行數(shù)據(jù)輸入或數(shù)據(jù)更新時(shí),系統(tǒng)要進(jìn)行檢查,以確保其數(shù)據(jù)的唯一性成立。
(3)加快表連接的速度。在進(jìn)行基本表的連接操作時(shí),系統(tǒng)需要對(duì)被連接的基本表的連接字段進(jìn)行查詢,其工作量是非常巨大的。如果在被連接的基本表的連接字段上創(chuàng)建索引,則可以大大提高連接操作的速度。因此,許多系統(tǒng)要求連接文件必須有相應(yīng)的索引才能執(zhí)行連接操作。
3.創(chuàng)建索引的原則
為了提高數(shù)據(jù)查詢的速度,在創(chuàng)建索引時(shí),應(yīng)遵循三個(gè)原則:
(1)索引的創(chuàng)建和維護(hù)由DBA和DBMS完成。索引由DBA或表的擁有者負(fù)責(zé)創(chuàng)建和撤銷,其他用戶不能隨意創(chuàng)建和撤銷索引。索引由系統(tǒng)自動(dòng)選擇和維護(hù),即不需要用戶指定使用索引,也不需要用戶打開索引或?qū)λ饕龍?zhí)行重索引操作,這些工作都由DBMS自動(dòng)完成。
(2)是否創(chuàng)建索引取決于表的數(shù)據(jù)量大小和對(duì)查詢的要求?;颈碇杏涗浀臄?shù)據(jù)量越大,記錄越長,越有必要?jiǎng)?chuàng)建索引,創(chuàng)建索引后加快查詢速度的效果會(huì)比較明顯。相反,對(duì)于記錄比較少的基本表,創(chuàng)建索引的意義則不大。另外,索引要根據(jù)數(shù)據(jù)查詢或處理的要求而創(chuàng)建。即對(duì)那些查詢頻度高、實(shí)時(shí)性要求高的數(shù)據(jù)一定要?jiǎng)?chuàng)建索引,否則不必考慮創(chuàng)建索引的問題。
(3)對(duì)于一個(gè)基本表,不要建立過多的索引。索引文件要占用文件目錄和存儲(chǔ)空間,索引過多會(huì)使系統(tǒng)負(fù)擔(dān)加重。索引需要自身維護(hù),當(dāng)基本表的數(shù)據(jù)增加、刪除或修改時(shí),索引文件要隨之變化,以保持與基本表一致。顯然,索引過多會(huì)影響數(shù)據(jù)增、刪、改的速度。
盡管使用索引可以強(qiáng)化數(shù)據(jù)庫的性能,但也有需要避免使用索引的時(shí)候,如下面所示的八種情況:
①包含太多重復(fù)值的列。
②查詢中很少被引用的列。
③值特別長的列。
④查詢返回率很高的列。
⑤具有很多NULL值的列。
⑥需要經(jīng)常插、刪、改的列。
⑦記錄較少的基本表。
⑧需要頻繁地進(jìn)行大量數(shù)據(jù)更新的基本表。
4.索引的類型及選擇
在數(shù)據(jù)庫中,對(duì)一張表可以創(chuàng)建不同類型的索引,而這些索引都具有相同的作用,即加快數(shù)據(jù)查詢速度以提高數(shù)據(jù)庫的性能。索引的一般類型有三種:
(1)單列索引。單列索引是對(duì)基本表的某一單獨(dú)的列進(jìn)行的索引,是最簡(jiǎn)單和最常用的索引類型,它是在表的某一列的基礎(chǔ)上建立的。
(2)唯一索引。唯一索引不允許在表中插入任何相同的取值。使用唯一索引不但能提高性能,還可以維護(hù)數(shù)據(jù)的完整性。
(3)復(fù)合索引。復(fù)合索引是針對(duì)表中兩個(gè)或兩個(gè)以上的列建立的索引。由于被索引列的順序?qū)?shù)據(jù)查詢速度具有顯著的影響,因此創(chuàng)建復(fù)合索引時(shí),應(yīng)當(dāng)考慮索引的性能。為了優(yōu)化性能,通常將最強(qiáng)限定值放在第一位。但是,那些始終被指定的列更應(yīng)當(dāng)放在第一位。
5.建立索引
在SQL語言中,使用CREATEINDEX語句建立索引,其一般格式如下:
CREATE[UNIQUE][CLUSTER]INDEX<索引名>
ON<表名>(<列名1>[<次序1>][,<列名2>[<次序2>]]…);
其中,<表名>是建立索引所依附的基本表,索引可以建立在此表的一列或多列上,各列之間用逗號(hào)分隔。每個(gè)列名都可以用ASC(升序)/DESC(降序)指定次序,缺省值為ASC。
UNIQUE表明此索引中若有重復(fù)記錄,其只保留對(duì)應(yīng)的一條數(shù)據(jù)記錄。
【例4.13】在USER1表的NAME(姓名)列上建立一個(gè)聚簇索引。
CREATECLUSTERINDEXUIDXONUSER1(NAME);
用戶一般可以在最常查詢的列上創(chuàng)建聚簇索引以提高查詢速度。聚簇索引一旦建立,再要更新索引列時(shí),會(huì)導(dǎo)致表中記錄的物理順序的變更,代價(jià)太大,而且一個(gè)基本表只能建一個(gè)聚簇索引,因此對(duì)于經(jīng)常更新的列不宜創(chuàng)建聚簇索引。
使用索引的原則:不應(yīng)該在一個(gè)表上建立太多的索引(一般不超過兩到三個(gè))。索引能改善查詢效果,但也耗費(fèi)了磁盤空間,降低了更新操作的性能,因?yàn)橄到y(tǒng)必須花時(shí)間來維護(hù)這些索引。除了為數(shù)據(jù)的完整性而建立的唯一索引外,建議在表較大時(shí)再建立普通索引。通常,表中的數(shù)據(jù)越多,索引的優(yōu)越性才越明顯。
【例4.14】為網(wǎng)上書店數(shù)據(jù)庫中的PRODUCT,SORTKIND,USER1_ORDER,ORDER_ITERM四個(gè)表上建立索引,其中在PRODUCT,SORTKIND表的ID列上建升序唯一索引,在USER1_ORDER表的USER1_ID列上建降序唯一索引,ORDER_ITERM表按ORDER_ID降序和PRODUCT_ID升序建唯一索引。
6.刪除索引
索引一旦建立,由系統(tǒng)使用和維護(hù),當(dāng)不需要時(shí),可刪除索引。在SQL語言中使用DROPINDEX語句刪除索引,一般格式如下:
DROPINDEX<索引名>;
如果數(shù)據(jù)增刪頻繁,系統(tǒng)會(huì)花費(fèi)許多時(shí)間來維護(hù)索引,從而會(huì)降低了查詢效率,故可以刪除一些不必要的索引。刪除索引時(shí),系統(tǒng)會(huì)同時(shí)刪除數(shù)據(jù)字典中有關(guān)該索引的定義。
在RDBMS中,索引一般采用B+樹、HASH索引來實(shí)現(xiàn)。B+樹索引具有動(dòng)態(tài)平衡的優(yōu)點(diǎn)。HASH索引具有查找速度快的特點(diǎn)。索引是關(guān)系數(shù)據(jù)庫的內(nèi)部實(shí)現(xiàn)技術(shù),屬于內(nèi)模式的范疇。
用戶使用CREATEINDEX語句定義索引時(shí),可以定義唯一索引、非唯一索引、聚簇索引。至于某個(gè)索引是采用B+樹,還是HASH索引則由具體的RDBMS決定。
【例4.15】刪除PRODUCT表中的PIDX索引。
DROPINDEXPIDX;
7.索引的優(yōu)點(diǎn)
創(chuàng)建索引有以下5個(gè)優(yōu)點(diǎn):
(1)創(chuàng)建唯一性索引,保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性。
(2)大大加快數(shù)據(jù)的檢索速度,這也是創(chuàng)建索引的最主要的原因。
(3)加速表和表之間的連接,特別是在實(shí)現(xiàn)數(shù)據(jù)的參考完整性方面特別有意義。
(4)在使用分組和排序子句進(jìn)行數(shù)據(jù)檢索時(shí),同樣可以顯著地減少查詢中分組和排序的時(shí)間。
(5)通過使用索引,可以在查詢的過程中使用優(yōu)化隱藏器,提高系統(tǒng)的性能。
8.索引的缺點(diǎn)
創(chuàng)建索引有以下3個(gè)缺點(diǎn):
(1)創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間,這種時(shí)間隨著數(shù)據(jù)量的增加而增加。
(2)索引需要占物理空間。除了數(shù)據(jù)表占數(shù)據(jù)空間之外,每一個(gè)索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會(huì)更大。
(3)當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候,索引也要進(jìn)行動(dòng)態(tài)的維護(hù),這就降低了數(shù)據(jù)的維護(hù)速度。
4.3.3SQLServer中數(shù)據(jù)定義的實(shí)現(xiàn)
說明:在SQL中語句需要以“;”結(jié)束,而在SQLServer中“;”是語句間的分隔符,并非是語句的組成部分,當(dāng)只有一條語句時(shí),“;”可以省略。
【例4.16】創(chuàng)建名為BOOKSTORES的數(shù)據(jù)庫。
CREATEDATABASEBOOKSTORES;
【例4.17】建立一個(gè)學(xué)生表STUDENT,它由學(xué)生號(hào)ID、姓名NAME、密碼PASSWORD、地址ADDRESS、郵編POSTCODE、電子郵箱EMAIL、宅電HOMEPHONE
7個(gè)屬性組成。其中ID為主鍵,姓名不能為空且值唯一,密碼也不許為空。
【例4.18】在學(xué)生表的ID(姓名)列上建立一個(gè)聚簇索引。
CREATECLUSTERINDEXIDXONSTUDENT(ID);
【例4.19】刪除SORTKIND表中的SIDX索引。
DROPINDEXSIDX;
4.4SQL數(shù)據(jù)更新功能
4.4.1插入操作
SQL語言中,數(shù)據(jù)插入語句INSERT通常有兩種形式,一種是一次插入一條元組,另一種是一次插入一個(gè)子查詢結(jié)果,即一次插入多條元組。
1.插入單條元組
在SQL語言中,插入單條元組的語句格式如下:
INSERT
INTO<表名>[(<屬性列1>[,<屬性列2>]…)
VALUES(<常量1>[,<常量2>]…);
INSERT語句的功能是將指定的元組插入到指定的關(guān)系中,其中屬性列的順序要與常量值的順序一一對(duì)應(yīng),常量1的值賦給屬性列1,常量2的值賦給屬性列2,依次賦值。
若在INTO子句中沒有出現(xiàn)的屬性列,則新值在這些列上取空值。必須注意,在表定義中不許為空的列不能取空值,否則會(huì)出錯(cuò)。
有時(shí)可以省略屬性列表,但常量的列表順序要求必須與指定關(guān)系的實(shí)際屬性列順序一致,且新插入的記錄必須在每個(gè)屬性列上均有值。
【例4.20】插入一條圖書類型記錄(
‘01’,‘計(jì)算機(jī)’)。
INSERT
INTOSORTKIND
VALUES(‘01’,‘計(jì)算機(jī)’);
【例4.21】將一個(gè)新書記錄(‘9787040123104’,‘?dāng)?shù)據(jù)庫系統(tǒng)教程’,29.5,‘施伯樂’,‘01’)插入到PRODUCT表中。
INSERT
INTOPRODUCT
(ID,NAME,PRICE,ZUOZHE,SORTKIND_ID)
VALUES(‘9787040123104’,‘?dāng)?shù)據(jù)庫系統(tǒng)教程’,
29.5,
‘施伯樂’,
‘01’);
新插入的記錄在DESCRIPTION、IMG列上自動(dòng)賦空值。
2.插入多個(gè)元組
在SQL語言中,子查詢結(jié)果可以一次性插入到指定的關(guān)系中。插入子查詢結(jié)果的語句格式如下:
INSERT
INTO<基本表名>[(<屬性列1>[,<屬性列2>…)]
<子查詢>;
說明:
①SQL先處理<子查詢>,得到查詢結(jié)果,再將結(jié)果插入到<基本表名>所指的基本表中。
②<子查詢>結(jié)果集合中的列數(shù)、列序和數(shù)據(jù)類型必須與<基本表名>所指基本表中相應(yīng)的各項(xiàng)匹配或兼容。
【例4.22】在PRODUCT表中查詢出所有01類圖書,將其圖書編號(hào)插入到USER1_ORDER訂單表中。
INSERT
INTOUSER1_ORDER(ID)
SELECTID
FROMPRODUCT
WHERESORTKIND_ID='01';
4.4.2修改操作
當(dāng)數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生變化時(shí),需要對(duì)關(guān)系進(jìn)行修改。在SQL語言中,修改操作的一般格式為
UPDATE<表名>
SET<列名>=<表達(dá)式>[,<列名>=<表達(dá)式>]...
[WHERE<條件>];
UPDATE語句的功能是修改指定關(guān)系中滿足WHERE子句條件的元組,其中SET子句給出指定列的修改方式及修改后取值。若省略WHERE子句,則說明要修改關(guān)系中的所有元組。在WHERE子句中可以嵌套子查詢。
1.修改某一個(gè)元組的值
【例4.23】將PRODUCT表中ID號(hào)為“9787040123104”的書的PRICE改為30元。
UPDATEPRODUCT
SETPRICE=30
WHEREID?=?‘9787040123104’;
2.修改多個(gè)元組的值
【例4.24】將PRODUCT表中所有圖書的PRICE加1元。
UPDATEPRODUCT
SETPRICE=PRICE+1;
3.帶子查詢的修改語句
【例4.25】將PRODUCT表中所有計(jì)算機(jī)類的圖書的PRICE提高5%。
4.4.3刪除操作
當(dāng)數(shù)據(jù)庫中的數(shù)據(jù)不再需要時(shí),應(yīng)將這些不需要的數(shù)據(jù)從關(guān)系中刪除。在SQL語言中,刪除語句的一般格式為
DELETE
FROM<表名>
[WHERE<條件>];
1.刪除某一個(gè)元組的值
【例4.26】將PRODUCT表中ID號(hào)為“9787040123104”的書刪除。
DELETE
FROMPRODUCT
WHEREID=‘9787040123104’;
2.刪除多個(gè)元組的值
【例4.27】將PRODUCT表中所有圖書刪除。
DELETE
FROMPRODUCT;
3.帶子查詢的刪除語句
【例4.28】將PRODUCT表中所有計(jì)算機(jī)類的圖書刪除。
4.4.4SQLServer中更新操作的實(shí)現(xiàn)
RDBMS在執(zhí)行更新語句時(shí)會(huì)檢查所做的更新操作是否破壞表上已定義的完整性規(guī)則,即實(shí)體完整性、參照完整性、用戶定義完整性(NOTNULL約束、UNIQUE約束、值域約束)。若破壞了表上定義的完整性約束規(guī)則,則更新失敗。
4.5SQL數(shù)據(jù)查詢功能
數(shù)據(jù)庫查詢是數(shù)據(jù)庫的核心操作。在SQL語言中,用SELECT語句進(jìn)行查詢。該語句具有靈活的使用方式和豐富的功能,其一般格式如下:
此語句含義為根據(jù)WHERE條件從FROM子句指定的表中選出滿足條件的元組,然后按SELECT子句后面指定的屬性列提取出指定的列。若有GROUPBY子句,再根據(jù)GROUPBY子句指出的<列名1>分組,屬性列值相等的為一組;若GROUPBY子句中有HAVING子句,則只有滿足HAVING條件的組才被輸出。若有ORDERBY子句,則將結(jié)果按<列名2>指定的順序排序。ASC為升序,DESC為降序,缺省時(shí)為ASC。
在SQL語言中,SELECT既可以實(shí)現(xiàn)單表的簡(jiǎn)單查詢,又可以實(shí)現(xiàn)多表的嵌套查詢和連接查詢。
4.5.1單表查詢
單表查詢指只涉及一個(gè)關(guān)系的查詢。
1.選擇關(guān)系中的若干列
選擇表中的所有列或部分列,即為投影運(yùn)算。
1)查詢?nèi)苛?/p>
選出表中的全部列有兩種方法。一種是在SELECT關(guān)鍵字后面列出所有的列名,并以“,”分割,指定的列順序可以不與表中順序一致;另一種是在SELECT關(guān)鍵字后面指定“*”,此時(shí)輸出列的順序必與原表順序一致。
【例4.38】查詢出全體用戶的詳細(xì)信息。
SELECT*
FROMUSER1;
等價(jià)于
SELECTID,NAME,PASSWORD,ADDRESS,POSTCODE,
EMAIL,HOME_PHONE,CELL_PHONE,OFFICE_PHONE
FROMUSER1;
2)查詢指定列
在多數(shù)情況下,用戶只對(duì)一部分列信息感興趣,此時(shí)就可以在SELECT子句后面指定要查詢的屬性列名。
3)查詢經(jīng)過計(jì)算的值
SELECT關(guān)鍵字后面的<目標(biāo)列表達(dá)式>既可是表中的屬性列,也可以是表達(dá)式。
2.選擇表中的若干元組
1)消除重復(fù)行
兩個(gè)并不相同的元組,投影到某些列后會(huì)出現(xiàn)相同的幾個(gè)元組,此時(shí)一般就需要消除重復(fù)元組。
【例4.43】查詢出訂購了圖書的用戶編號(hào)。
SELECTUSER1_ID
FROMUSER1_ORDER;
由于同一個(gè)用戶可能訂購多種圖書,所以上例中得到的USER1_ID可能會(huì)有重復(fù)值。如果要去掉重復(fù)值,則必須用DISTINCT關(guān)鍵字。若沒有DISTINCT關(guān)鍵字,則為ALL,即不消除重復(fù)值。要特別注意的是,DISTINCT修飾的是其后面的所有列。
2)查詢出滿足條件的元組
用WHERE子句指定查詢中需要滿足的條件,WHERE子句常用的查詢條件如表4.4所示。
(2)確定范圍。
BETWEEN…AND…可以用來查詢?cè)谥付ǚ秶鷥?nèi)的元組,其指定的是閉區(qū)間,BETWEEN后為下限,AND后為上限。NOTBETWEEN…AND…用來查詢不在指定范圍內(nèi)的元組。
(3)字符匹配。
用LIKE謂詞進(jìn)行字符匹配。其一般格式如下:
[NOT]LIKE‘<匹配串>’[ESCAPE‘<換碼字符>’]
上述語句的功能是查詢指定屬性列值與<匹配串>相匹配的元組。<匹配串>可以是一個(gè)不含通配符的完整字符串(當(dāng)<匹配串>為不含通配符的完整字符串時(shí),LIKE可用“=”號(hào)代替,NOTLIKE可用“!=”代替),也可以含有通配符“%”和“_”。
其中,“%(百分號(hào))”代表出現(xiàn)在指定位置的任意長度(長度可以為0)的字符串;“_(下劃線)代”表出現(xiàn)在指定位置的任意單個(gè)字符。
(4)確定集合。
用IN謂詞可以查找屬性值在指定的集合中的元組。
(5)復(fù)合條件查詢。
邏輯運(yùn)算符AND和OR可用來連接多條件查詢,條件運(yùn)算順序?yàn)閺淖蟮接遥褹ND優(yōu)先級(jí)高于OR,但用戶可以用括號(hào)改變優(yōu)先級(jí)。
(6)涉及空值的查詢。
3)對(duì)查詢結(jié)果進(jìn)行排序
在SQL語言中,SELECT查詢可以用ORDERBY子句對(duì)查詢結(jié)果進(jìn)行排序,可以根據(jù)一個(gè)屬性排序,也可以按照多個(gè)屬性排序。
4)函數(shù)查詢
SQL語言中為方便用戶使用,提供了許多聚集函數(shù),常用的SQL聚集函數(shù)如表4.5所示。
5)對(duì)查詢結(jié)果進(jìn)行分組
GROUPBY子句將查詢結(jié)果按照某一列或某幾列進(jìn)行分組,值相等的為一組。
4.5.2連接查詢
1.普通連接
普通連接操作只輸出滿足連接條件的元組。連接查詢中用來連接兩個(gè)表的條件稱為連接條件或連接謂詞,連接謂詞中的列名稱為連接字段,其一般格式為
[<表名1>.]<列名1><比較運(yùn)算符>[<表名2>.]<列名2>
[<表名1>.]<列名1>BETWEEN[<表名2>.]<列名2>AND[<表名2>.]<列名3>
連接條件中的各連接字段類型必須是可比的,但名字不必是相同的。連接條件要在WHERE子句中。
【例4.67】查詢出每個(gè)用戶及其訂購圖書的信息。
SELECTUSER1.*,USER1_ORDER.*
FROMUSER1,USER1_ORDER
WHEREUSER1.ID=USER1_ORDER.USER1_ID;/*將兩表中同一用戶的信息連接起來*/
在連接查詢中,為了避免混淆,要在屬性名前面加上表名前綴。如果屬性名在參加連接的表中是唯一的,則可以省略表名前綴。
若沒有指定兩表的連接條件,則兩表做廣義笛卡爾積,即兩表元組交叉乘積,其連接結(jié)果會(huì)產(chǎn)生一些沒有意義的元組,所以這種運(yùn)算實(shí)際上很少用。
若連接條件中的連接運(yùn)算符是等號(hào)(=),則該連接是等值連接,其中會(huì)有相同的重復(fù)屬性列。如果去掉重復(fù)的屬性列,則是自然連接。
一般情況下,并不需要將兩個(gè)表中的所有屬性列均顯示出來,只是將用戶需要的屬性列在SELECT子句中列出來即可。在指定輸出的屬性列中,如果有兩個(gè)表中都存在的屬性,則需要在屬性名前面加上表名前綴,否則不需要加表名前綴。
【例4.68】查詢出訂購圖書的用戶姓名、訂單編號(hào)和訂單金額。
SELECTUSER1.NAME,USER1_ORDER.ID,COST
FROMUSER1,USER1_ORDER
WHEREUSER1.ID=USER1_ORDER.USER1_ID;/*將兩個(gè)表中同一用戶的信息連接起來*/
COST屬性前面沒有加表名前綴,是因?yàn)橹挥蠻SER1_ORDER表中有COST屬性,不會(huì)引起混淆。
連接不僅可以在兩個(gè)不同的表中進(jìn)行,也可以是一個(gè)表與其自身進(jìn)行連接,稱為自身連接,這種連接在實(shí)際查詢中經(jīng)常會(huì)用到。
注意:連接查詢方式只用一個(gè)查詢塊,并且必須在WHERE子句中給出連接謂詞。當(dāng)目標(biāo)列中涉及的屬性在不同表中時(shí),只能使用連接查詢方式進(jìn)行查詢。
2.外連接
通常情況下,連接操作只會(huì)將滿足條件的元組作為結(jié)果輸出,例如USER1表和USER1_ORDER表做普通連接時(shí)只會(huì)輸出滿足條件的元組,沒有訂購圖書的用戶就不會(huì)顯示出來。但有時(shí)我們想要以USER1表為主體列出每個(gè)用戶的基本情況及其訂購圖書的情況(若某個(gè)用戶沒有訂購圖書,只輸出其用戶基本信息,其訂購圖書的信息為空即可),這時(shí)就需要應(yīng)用外連接(OUTERJOIN)。
3.復(fù)合條件連接
在上面的例子中,WHERE條件中只有一個(gè)條件,但多數(shù)時(shí)候WHERE子句中會(huì)有多個(gè)條件,這就稱為復(fù)合條件連接。
4.5.3嵌套查詢
在SQL語言中,一個(gè)SELECT—FROM—WHERE語句稱為一個(gè)查詢塊。將一個(gè)查詢塊嵌套在另一個(gè)查詢塊的WHERE子句或HAVING短語的條件中的查詢稱為嵌套查詢(NestedQuery)。
1.帶有IN謂詞的子查詢
在嵌套查詢中,子查詢的結(jié)果往往是一個(gè)集合,所以謂詞IN是嵌套查詢中最常用的謂詞。
【例4.72】查詢出計(jì)算機(jī)類的圖書編號(hào)及圖書名稱。
先分步完成子查詢,然后再構(gòu)造嵌套查詢。
①先確定計(jì)算機(jī)類圖書的編號(hào)。
SELECTID
FROMSORTKIND
WHERENAME='計(jì)算機(jī)';
【例4.73】查詢出用戶姓名為“李平”的用戶訂購的訂單編號(hào)及訂單金額。
2.帶有比較運(yùn)算符的子查詢
當(dāng)子查詢結(jié)果返回的是一個(gè)單值時(shí),父查詢和子查詢之間可以用比較運(yùn)算符>,>=,<,<=,=,!=,<>等進(jìn)行連接。
例如,在例4.72中,由于計(jì)算機(jī)類的圖書類型編號(hào)只有一個(gè),也就是說內(nèi)查詢結(jié)果只返回一個(gè)值,因此可以用“=”代替IN,其SQL語句如下:
這個(gè)語句的一個(gè)可能的執(zhí)行過程是:
①從外層查詢中取出USER1_ORDER的一個(gè)元組X,將元組X的USER1_ID值(001)傳送給內(nèi)層查詢。
SELECTAVG(COST)
FROMUSER1_ORDERY
WHEREY.USER1_ID='001';
②執(zhí)行內(nèi)層查詢,得到值24,用該值代替內(nèi)層查詢,得到外層查詢。
SELECTUSER1_ID,ID
FROMUSER1_ORDERX
WHERECOST>=24;
③執(zhí)行這個(gè)查詢,得到一組結(jié)果。
④外層查詢?nèi)〕鱿乱粋€(gè)元組重復(fù)做上述①至③步驟,直到外層的USER1_ORDER元組全部處理完畢,得到查詢的全部結(jié)果。
求解相關(guān)子查詢不像求解不相關(guān)子查詢那樣,一次將子查詢求解出來,然后求解父查詢。內(nèi)查詢由于與外查詢有關(guān),因此必須反復(fù)求值。
3.帶有ANY和ALL謂詞的子查詢
單獨(dú)使用比較運(yùn)算符時(shí),要求子查詢返回的結(jié)果必須為單值。若子查詢返回的是一個(gè)集合,就要使用帶有ANY和ALL謂詞的比較運(yùn)算符,其語義組合如表4.6所示。
實(shí)際上用聚集函數(shù)實(shí)現(xiàn)子查詢通常比直接使用ANY或ALL查詢效率要高,ANY、ALL謂詞與聚集函數(shù)、IN謂詞的等價(jià)轉(zhuǎn)換關(guān)系如表4.7所示。
4.5.4集合查詢
因?yàn)镾ELECT語句的查詢結(jié)果是元組的集合,所以多個(gè)SELECT語句的結(jié)果可以進(jìn)行集合操作。集合操作的種類主要有并操作UNION、交操作INTERSECT、差操作EXCEPT。參加集合操作的各查詢結(jié)果的列數(shù)必須相同,對(duì)應(yīng)項(xiàng)的數(shù)據(jù)類型也必須相同。
【例4.75】查詢出01類的圖書或價(jià)格在30元以上的圖書編號(hào)及其圖書名稱。
4.5.5SELECT語句的一般格式
SELECT語句是SQL的核心語句。從上面的例子可以看到其語句成分豐富多樣,下面我們總結(jié)一下它們的一般格式。
1.目標(biāo)列表達(dá)式格式
目標(biāo)列表達(dá)式格式有以下4種:
(1)?*。
(2)
<表名>.*。
(3)
COUNT([DISTINCT|ALL]*)。
(4)
[<表名>.]<屬性列名表達(dá)式>[,[<表名>.]<屬性列名表達(dá)式>]…。
其中,<屬性列名表達(dá)式>是由屬性列、作用于屬性列的聚集函數(shù)和常量的任意算術(shù)運(yùn)算符(+,-,*,/
)?組成的運(yùn)算公式。
2.聚集函數(shù)的一般格式
聚集函數(shù)的一般格式如下:
3.條件表達(dá)式格式
條件表達(dá)式有以下7種格式:
4.5.6SQLServer中數(shù)據(jù)查詢的實(shí)現(xiàn)
4.6SQL數(shù)據(jù)控制功能
數(shù)據(jù)控制亦稱為數(shù)據(jù)保護(hù),包括數(shù)據(jù)的安全性控制、完整性控制、并發(fā)控制和恢復(fù)。SQL語言提供了數(shù)據(jù)控制功能,能夠在一定程度上保證數(shù)據(jù)庫中數(shù)據(jù)的安全性、完整性,并提供了一定的并發(fā)控制及恢復(fù)能力。
4.6.1授權(quán)操作
GRANT語句的一般格式:
GRANT<權(quán)限>[,<權(quán)限>]...
[ON<對(duì)象類型><對(duì)象名>]
TO<用戶>[,<用戶>]...
[WITHGRANTOPTION];
GRANT語句的語義是將指定操作對(duì)象的指定操作權(quán)限授予指定的用戶。發(fā)出該GRANT語句的可以是DBA,也可以是該數(shù)據(jù)庫對(duì)象的創(chuàng)建者(基本表的屬主),還可以是已經(jīng)擁有該權(quán)限的用戶。該授權(quán)的用戶可以是一個(gè)或多個(gè)具體用戶,也可以是PUBLIC用戶,即全體用戶。
如果指定了WITHGRANTOPTION子句,則獲得某種權(quán)限的用戶還可以把這種權(quán)限再授予別的用戶,但不許循環(huán)授權(quán),即被授權(quán)者不能再把權(quán)限授回給授權(quán)者或其祖先,如圖4.3所示。
對(duì)不同類型的操作對(duì)象有不同的操作權(quán)限,常見的操作權(quán)限如表4.8所示。
圖4.3不允許循環(huán)授權(quán)
【例4.95】DBA把在網(wǎng)上書店數(shù)據(jù)庫中建立表的權(quán)限授予用戶U8。
GRANTCREATETABLE
TOU8;
4.6.2收回權(quán)限操作
用戶被授予的權(quán)限可由DBA或其他授權(quán)者用REVOKE語句收回。REVOKE語句的一般格式為
REVOKE<權(quán)限>[,<權(quán)限>]...
[ON<對(duì)象類型><對(duì)象名>]
FROM<用戶>[,<用戶>]...;
將用戶U5的INSERT權(quán)限收回的時(shí)候,必須級(jí)聯(lián)(CASCADE)收回,即系統(tǒng)只收回直接或間接從U5處獲得的權(quán)限,否則系統(tǒng)將拒絕(RESTRICT)執(zhí)行此命令。
系統(tǒng)將收回直接或間接從U5處獲得的對(duì)USER1_ORDER表的INSERT權(quán)限,過程如下:
→U5→U6→U7
收回U5、U6、U7獲得的對(duì)USER1_ORDER表的INSERT權(quán)限的過程是:←U5←U6←U7。由上面的例子可見,SQL提供了非常靈活的授權(quán)機(jī)制。DBA擁有對(duì)數(shù)據(jù)庫中所有對(duì)象的所有權(quán)限,并且可以根據(jù)需要將權(quán)限授予不同用戶。
4.6.3SQLServer中數(shù)據(jù)控制的實(shí)現(xiàn)
4.7視圖
視圖是從一個(gè)或幾個(gè)基本表(或視圖)導(dǎo)出的表,它與基本表不同,是一個(gè)虛表。數(shù)據(jù)庫中只存放視圖的定義,而不存放視圖對(duì)應(yīng)的數(shù)據(jù),這些數(shù)據(jù)仍然存放在原來的基本表中。所以,若基本表數(shù)據(jù)發(fā)生變化,則視圖中的數(shù)據(jù)也會(huì)隨之發(fā)生變化。從這個(gè)意義上講,視圖是數(shù)據(jù)庫的一個(gè)窗口,透過視圖可以看見數(shù)據(jù)庫中自己感興趣的數(shù)據(jù)及其變化情況。
4.7.1視圖定義
1.創(chuàng)建視圖
在SQL語言中,用CREATEVIEW命令建立視圖,其一般語句格式為
CREATEVIEW
<視圖名>[(<列名>[,<列名>]…)]
AS<子查詢>
[WITHCHECKOPTION];
其中,子查詢可以是任意復(fù)雜的SELECT語句,但通常不能含有ORDERBY子句和DISTINCT短語;WITHCHECKOPTION透過視圖進(jìn)行增刪改操作時(shí),不得破壞視圖定義中的謂詞條件(即子查詢中的條件表達(dá)式)。
組成視圖的屬性列名或全部省略或全部指定。如果省略了視圖的各個(gè)屬性列名,則隱含指明該視圖由子查詢中SELECT目標(biāo)列中的諸字段組成。但下面四種情況必須明確指定視圖的所有列名:
①某個(gè)目標(biāo)列是聚集函數(shù)或列表達(dá)式。
②目標(biāo)列為*。
③多表連接時(shí)選出了幾個(gè)同名列作為視圖的字段。
④需要在視圖中為某個(gè)列啟用新的更合適的名字。
(1)行列子集視圖。
若一個(gè)視圖由一個(gè)基本表導(dǎo)出,并且只是去掉了基本表中的若干行和若干列,但保留了碼,我們稱這類視圖為行列子集視圖。
【例4.105】建立01類圖書的視圖,并要求透過該視圖進(jìn)行的更新操作只涉及01類圖書。
由于定義視圖時(shí)加上了WITHCHECKOPTION子句,以后對(duì)該視圖進(jìn)行更新時(shí)DBMS將自動(dòng)加上SORTKIND_ID='01'條件。
(3)基于多個(gè)基表的視圖。
【例4.106】建立計(jì)算機(jī)類的圖書視圖。
(4)基于視圖的視圖。
【例4.107】建立計(jì)算機(jī)類且圖書價(jià)格大于20元的視圖。
(5)帶表達(dá)式的視圖。
【例4.108】定義一個(gè)反映圖書9折價(jià)格的視圖。
設(shè)置派生屬性列(也稱為虛擬列SALE_PRICE)時(shí),帶表達(dá)式的視圖必須明確定義組成視圖的屬性列名。
(6)分組視圖。
【例4.109】將圖書的類型編號(hào)及它的平均價(jià)格定義為一個(gè)視圖。
【例4.110】建立01類圖書的視圖。
2.刪除視圖
在SQL語言中,用DROPVIEW語句刪除視圖,其一般語句格式為
DROPVIEW<視圖名>;
該語句從數(shù)據(jù)字典中刪除指定的視圖定義,由該視圖導(dǎo)出的其他視圖定義仍在數(shù)據(jù)字典中,但已不能使用,必須顯式刪除。
【例4.111】刪除視圖IS_PRODUCT。
DROPVIEWIS_PRODUCT;
4.7.2視圖查詢
視圖定義之后,用戶可以像查詢基本表一樣查詢視圖。DBMS實(shí)現(xiàn)視圖查詢的方法一般有兩種:實(shí)體化視圖(ViewMaterialization)、視圖消解法(ViewResolution)。
實(shí)體化視圖(ViewMaterialization),首先進(jìn)行有效性檢查,檢查所查詢的視圖是否存在。如果存在,則取出并執(zhí)行視圖定義,將視圖臨時(shí)實(shí)體化,生成臨時(shí)表,進(jìn)而將查詢視圖轉(zhuǎn)換為查詢臨時(shí)表,查詢完畢刪除被實(shí)體化的視圖(臨時(shí)表)。
視圖消解法(ViewResolution),首先進(jìn)行有效性檢查,檢查查詢的表、視圖等是否存在。如果存在,則從數(shù)據(jù)字典中取出視圖的定義,把視圖定義中的子查詢與用戶的查詢結(jié)合起來,轉(zhuǎn)換成等價(jià)的對(duì)基本表的查詢,最后執(zhí)行修正后的查詢。
視圖消解法的局限:有些情況下,視圖消解法不能生成正確查詢,因?yàn)椴捎靡晥D消解法的DBMS會(huì)限制這類查詢。
4.7.3視圖更新
從用戶角度來看,更新視圖與更新基本表相同。更新視圖是指通過視圖來插入(INSERT)、刪除(DELETE)和修改(UPDATE)數(shù)據(jù)。
由于視圖是不實(shí)際存儲(chǔ)數(shù)據(jù)的表,所以對(duì)視圖的更新,最終要轉(zhuǎn)換為對(duì)基本表的更新。像查詢視圖那樣,對(duì)視圖的更新操作也可以通過視圖消解法轉(zhuǎn)換為對(duì)基本表的更新操作。
為了防止用戶通過視圖對(duì)不屬于視圖范圍的基本表數(shù)據(jù)進(jìn)行操作,可以在定義視圖時(shí)加上WITHCHECKOPTION子句。這樣在視圖上更新視圖時(shí),RDBMS就會(huì)檢查視圖定義中的條件,若不滿足條件,則拒絕執(zhí)行該操作。
實(shí)際系統(tǒng)允許對(duì)行列子集視圖進(jìn)行更新,對(duì)其他類型視圖的更新,不同系統(tǒng)有不同限制。DB2對(duì)視圖更新的限制有:
(1)若視圖是由兩個(gè)以上基本表導(dǎo)出的,則此視圖不允許更新。
(2)若視圖的字段來自字段表達(dá)式或常數(shù),則不允許對(duì)此視圖執(zhí)行INSERT和UPDATE操作,但允許執(zhí)行DELETE操作。
(3)若視圖的字段來自聚集函數(shù),則此視圖不允許更新。
(4)若視圖定義中含有GROUPBY子句,則此視圖不允許更新。
(5)若視圖定義中含有DISTINCT短語,則此視圖不允許更新。
(6)若視圖定義中有嵌套查詢,并且內(nèi)層查詢的FROM子句中涉及的表也是導(dǎo)出該視圖的基本表,則此視圖不允許更新。
(7)一個(gè)不允許更新的視圖上定義的視圖也不允許更新。
4.7.4SQLServer中的視圖操作
4.8嵌入式SQL
SQL語言的特點(diǎn)之一就是在兩種使用方式下,SQL語言的語法結(jié)構(gòu)基本上是一致的。當(dāng)然細(xì)節(jié)上會(huì)有許多差異,在程序設(shè)計(jì)的環(huán)境下,SQL語句要做一些必要的擴(kuò)充。
4.8.1嵌入式SQL的概述
SQL語言提供了兩種不同的使用方式:交互式、嵌入式。對(duì)嵌入式SQL,RDBMS一般采用預(yù)編譯方法處理,即由RDBMS的預(yù)處理程序?qū)υ闯绦蜻M(jìn)行掃描,識(shí)別出SQL語句,把它們轉(zhuǎn)換成主語言調(diào)用語句,以使主語言編譯程序能識(shí)別它,最后由主語言的編譯程序?qū)⒄麄€(gè)源程序編譯成目標(biāo)碼。為了區(qū)分SQL語句與主語言語句,需要在所有SQL語句前加前綴EXECSQL,其結(jié)束標(biāo)志隨主語言的不同而不同。
嵌入了SQL的應(yīng)用程序的執(zhí)行過程如圖4.4所示。
圖4.4嵌入了SQL的應(yīng)用程序的執(zhí)行過程
以C為主語言的嵌入式SQL語句的一般形式為
EXECSQL<SQL語句>;
例:EXECSQLDROPTABLEPRODUCT;
以COBOL作為主語言的嵌入式SQL語句的一般形式為
EXECSQL<SQL語句>END-EXEC
例:EXECSQLDROPTABLEPRODUCTEND-EXEC
注意:嵌入式SQL語句根據(jù)作用的不同,可分為可執(zhí)行語句和說明性語句。允許出現(xiàn)可執(zhí)行的高級(jí)語言語句的地方,都可以寫可執(zhí)行SQL語句;允許出現(xiàn)說明語句的地方,都可以寫說明性SQL語句。
4.8.2嵌入式SQL語句與主語言之間的通信
將SQL語言嵌入高級(jí)語言中進(jìn)行混合編程時(shí),SQL語言中描述性的面向集合的語句負(fù)責(zé)操縱數(shù)據(jù)庫,高級(jí)語言中過程性的面向記錄的語句負(fù)責(zé)控制程序流程。這時(shí),程序中會(huì)含有兩種不同計(jì)算模型的語句,它們之間應(yīng)該如何通信呢?
數(shù)據(jù)庫工作單元和源程序工作單元之間的通信主要包括以下三個(gè)方面:
(1)向主語言傳遞SQL語句的執(zhí)行狀態(tài)信息,使主語言能夠據(jù)此控制程序流程,主要用SQL通信區(qū)(SQLCommunicationArea,SQLCA)實(shí)現(xiàn)。
(2)主語言向SQL語句提供參數(shù),主要由主變量(HostVariable)實(shí)現(xiàn)。
(3)將SQL語句查詢數(shù)據(jù)庫的結(jié)果交主語言進(jìn)一步處理,主要由主變量和游標(biāo)(Cursor)實(shí)現(xiàn)。
1.
SQL通信區(qū)
SQL語句執(zhí)行后,DBMS反饋給應(yīng)用程序若干信息,這些信息主要包括描述系統(tǒng)當(dāng)前工作狀態(tài)和描述運(yùn)行環(huán)境兩方面內(nèi)容。再將這些信息送到SQL通信區(qū)(SQLCA)中,應(yīng)用程序從SQLCA中取出這些狀態(tài)信息,據(jù)此決定接下來的執(zhí)行語句。
SQLCA的內(nèi)容既與所執(zhí)行的SQL語句有關(guān),又與該SQL語句的執(zhí)行情況有關(guān)。例如在執(zhí)行刪除語句DELETE后,不同的執(zhí)行情況,SQLCA中會(huì)有不同的信息:若違反數(shù)據(jù)保護(hù)規(guī)則,則操作拒絕;若沒有滿足條件的行,則一行也不會(huì)被刪除;若成功刪除,則顯示刪除的行數(shù);若無條件刪除,則顯示警告信息;由于各種原因,執(zhí)行出錯(cuò)等。
SQLCA是一個(gè)數(shù)據(jù)結(jié)構(gòu),在使用SQLCA之前,應(yīng)用EXECSQLINCLUDESQLCA加以定義。SQLCA中有一個(gè)存放每次執(zhí)行SQL語句后返回代碼的變量SQLCODE。如果SQLCODE等于預(yù)定義的常量SUCCESS,則表示SQL語句執(zhí)行成功,否則表示出錯(cuò)。應(yīng)用程序每執(zhí)行完一條SQL語句之后都應(yīng)該測(cè)試一下SQLCODE的值,以了解該SQL語句的執(zhí)行情況并做相應(yīng)處理。
2.主變量
在SQL語句中,使用的主語言程序變量簡(jiǎn)稱為主變量(HostVariable),嵌入式SQL語句中可以用主變量來輸入或輸出數(shù)據(jù)。根據(jù)作用不同,主變量分為兩種類型:輸入主變量,由應(yīng)用程序?qū)ζ滟x值,SQL語句引用;輸出主變量,由SQL語句賦值或設(shè)置狀態(tài)信息,返回給應(yīng)用程序。有時(shí),一個(gè)主變量有可能既是輸入主變量又是輸出主變量。
一個(gè)主變量可以附帶一個(gè)指示變量(IndicatorVariable)。指示變量是一個(gè)整型變量,用來“指示”所指主變量的值或條件。輸入主變量可以利用指示變量賦空值。輸出主變量可以利用指示變量檢測(cè)出是否空值,或值是否被截?cái)唷?/p>
對(duì)主變量說明之后,它便可以在SQL語句中任何一個(gè)能夠使用表達(dá)式的地方出現(xiàn)。為了與數(shù)據(jù)庫對(duì)象名(表名、視圖名、列名等)區(qū)別,SQL語句中的主變量名前要加冒號(hào)“:”作為標(biāo)志。指示變量前也必須加冒號(hào)標(biāo)志,且要緊跟在所指主變量之后。在SQL語句之外(主語言語句中)使用主變量和指示變量可以直接引用,不必加冒號(hào)。
3.游標(biāo)(Cursor)
SQL語言與主語言具有不同的數(shù)據(jù)處理方式。SQL語言是面向集合的,一條SQL語句原則上可以產(chǎn)生或處理多條記錄,而主語言是面向記錄的,一組主變量一次只能存放一條記錄,故僅使用主變量并不能完全滿足SQL語句向應(yīng)用程序輸出數(shù)據(jù)的要求。因此,嵌入式SQL引入了游標(biāo)的概念,用來協(xié)調(diào)這兩種不同的處理方式。
游標(biāo)是系統(tǒng)為用戶開設(shè)的一個(gè)數(shù)據(jù)緩沖區(qū),用來存放SQL語句的執(zhí)行結(jié)果。每個(gè)游標(biāo)區(qū)都有一個(gè)名字,用戶可以用SQL語句逐一從游標(biāo)中獲取記錄,并賦給主變量,再交由主語言進(jìn)一步處理。
4.8.3不使用游標(biāo)的SQL語句
不使用游標(biāo)的語句有:
·
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 維也納客戶協(xié)議書
- 博云開源協(xié)議書
- 維保協(xié)議維保合同
- 租賃醫(yī)師證協(xié)議書
- 打字勞動(dòng)合同范本
- 合伙分家協(xié)議書
- 店員用工合同范本
- 供電擔(dān)保協(xié)議書
- 借戶上學(xué)協(xié)議書
- 借名入戶協(xié)議書
- GB/T 31402-2015塑料塑料表面抗菌性能試驗(yàn)方法
- GB/T 20969.3-2007特殊環(huán)境條件高原機(jī)械第3部分:高原型工程機(jī)械選型、驗(yàn)收規(guī)范
- 最新-脂肪性肝病課件
- 眼科OCT異常圖譜解讀
- 保密工作知識(shí)講課稿范文(通用3篇)
- DB11- 996-2013-城鄉(xiāng)規(guī)劃用地分類標(biāo)準(zhǔn)-(高清有效)
- 風(fēng)光互補(bǔ)系統(tǒng)實(shí)驗(yàn)(圣威科技)王鑫
- 1-院前急救風(fēng)險(xiǎn)管理
- 古典園林分析之郭莊講解課件
- 核電工程質(zhì)量保證知識(shí)培訓(xùn)教材PPT課件
- 交管12123駕照學(xué)法減分題庫及答案共155題(完整版)
評(píng)論
0/150
提交評(píng)論