《資料庫系統概論》學習總結
1. 資料探勘是從資料庫中發現知識,或者主要是從大量的磁碟資料中發現知識。它與機器學習和統計分析不一樣。
2. 資料庫管理系統(Database-Management System, DBMS)由一個互相關聯的資料的集合和一組用於訪問這些資料的程式組成。這個資料集合通常稱為資料庫(database)。DBMS的主要目標是要提供一種可以方便、高效地存取資料庫資訊的途徑。
3. 資料庫結構的基礎是資料模型。資料模型是一個描述資料、資料聯絡、資料語義以及一致性約束的概念工具的集合。資料模型提供了一種描述物理層、邏輯層和檢視層資料庫設計的方式。
資料模型可被劃分為四類:
1) 關係模型(relationship model)。關係模型用表的集合來表示資料和資料間的聯絡。
2) 實體-聯絡模型(entity-relationship model)。將現實世界的一件“事情”或一件“事物”視為一個實體,以實體作為基本物件。實體-聯絡模型就是將基本物件以及這些物件間的聯絡構成。所有實體集合稱為實體集,同一型別的所有聯絡的集合稱為聯絡集。該模型廣泛用於資料庫設計。
3) 基於物件的資料模型(object-based data model)。面向物件的資料模型可以看成是E-R模型增加了封裝、方法(函式)和物件標識等概念後的擴充套件。物件-關係資料模型結合了面向物件的資料模型和關係資料模型的特徵。
4) 半結構化的資料模型(semistructured data model)。該模型允許相同的資料項含有不同的屬性集的資料定義。而之前提到的資料模型:所有某種特定的資料項必須有相同的屬性集。比如XML(extensible markup language)可擴充套件標記語言。
5) 網狀資料模型(network data model)。該模型已經很少用了,先於關係模型。
6) 層次資料模型(hierarchical data model)。該模型已經很少用了,先於關係模型。
4. 資料庫語言分為:
1) 資料定義語言(data –definition language,DDL),通過它可以定義表、完整性約束、斷言,等等。使用者和資料庫管理系統都能用它。
2) 資料操縱語言(data-manipulation language,DML)。分為兩種:
a. 過程化DML。要求使用者指定需要什麼資料並且給出如何獲得這些資料的途徑。
b. 宣告式DML。要求使用者指定需要什麼資料就行,不必指明如何獲得這些資料資訊。SQL查詢語句是非過程化的,也即宣告式的。
5. 資料庫系統的大致功能部件可以分為:儲存管理器和查詢管理器。
儲存管理器部件包括:
a. 許可權及完整性管理器(authorization and integrity manager)
b. 事務管理器(transaction manager)
c. 檔案管理器(file manager)
d. 快取區管理器(buffer manager)
e. 資料檔案(data files)
f. 資料字典(data dictionary)
g. 索引(index)
查詢管理器部件包括:
a. DDL直譯器(DDL interpreter)
b. DML編譯器(DML compiler)
c. 查詢執行引擎(query evaluation engine)
6. 超碼(superkey)是一個或多個屬性的集合,這些屬性的集合可以使我們在一個關係中唯一標識一個元組。如果K為超碼,則K的任意超集也為超碼。如果K為超碼並且K的任意真子集都不為超碼,則K稱為候選碼,也就是最小的超碼。超碼也可以理解成在候選碼上擴充套件其他屬性。為了區分不同的候選碼,從中選擇一個作為主碼。關係中的任意兩個不同的元組都不允許同時在碼(不論是主碼、候選碼或者超碼)屬性上具有相同的值。碼是整個關係的一種性質,而不是單個元組的性質。
7. 外碼(foreign key)定義:如果一個關係模式(r1)可能在它的屬性中包含另一個關係模式(r2)的主碼,這個屬性在r1上稱為外碼,準確的說是關係r1參照關係r2的外碼。其中,r1稱為參照關係,r2稱為被參照關係。在定義一個關係的外碼時,該關係就存在外碼約束了。外碼約束比參照完整性約束條件更為苛刻。
8. 參照完整性約束(referential integrityconstraint)的參照屬性在另一個關係模式r2中未必是主碼,而外碼約束必須是主碼。所以,外碼約束包含於參照完整性約束中。參照完整性約束又稱為子集依賴(subset dependency)。參照完整性約束要求:在參照關係中任意元組在特定的屬性上的取值必然等於被參照關係中某個元組在特定的屬性上的取值。
9. 大學資料庫模式:
classroom ( building,room_number, capacity )
department( dept_name,building, budget )
course( course_id,title,dept_name, credits )
instructor( ID,name, dept_name, salary )
section( course_id,sec_id, semester, year, building, room_number,time_slot_id )
teaches( ID, course_id,sec_id, semester, year )
student( ID, name,dept_name, tot_cred )
takes( ID, course_id,sec_id, semester, year, grade )
advisor( s_ID,i_ID )
time_slot( time_slot_id,day, start_time, end_time )
prereq( course_id, prereq_id )
10. 外來鍵不可能在本關係中作主鍵或作為主鍵的一部分。(此話有誤)
11. 外碼中的屬性允許為空(null),只要它們沒有被宣告為not null。有個規定:如果某外碼列為空null,則該元組自動被認為是滿足外碼約束。
12. 參照完整性約束有以下幾種:
1) 外碼約束。在SQL create table 中外碼參照預設情況下是被參照表中的主碼屬性。
如:foreign key (dept_name) referencesdepartment 其中dept_name屬性在department 表中作為主碼。
外碼約束可以作為屬性定義的一部分,同時宣告該屬性為外碼,如:
dept_name varchar(20) referencesdepartment
create table advisor
(s_ID varchar(5),
i_IDvarchar(5),
primary key (s_ID),
foreign key (s_ID) references student(ID) ondelete cascade,
foreign key (i_ID) references instructor(ID)on delete set null
);
2) SQL支援顯示指定被參照關係屬性列表的references 子句。但是,這個指定的屬性列表必須宣告為被參照關係的候選碼,或者是使用了primary key 約束,或者是使用了unique約束。(references子句出現的屬性只能是主碼、候選碼和unique屬性)
3) 更為普遍地參照完整性約束。在更普遍的參照完整性約束形式中,被參照的屬性不必是候選碼,這樣的形式還不能在SQL中直接宣告。但是,SQL標準提供了另外的結構用於實現這樣的約束,比如:
a. 複雜check 條件和斷言
b. 觸發器
13. 當違反參照完整性約束時,通常的處理是拒絕執行導致完整性破壞的操作(即進行更新操作的事務被回滾)。但是,在foreign key 中可以指明:如果被參照的關係上的元組刪除或者更新動作違反了約束,那麼系統根據foreign key子句定義的要求來恢復完整性約束,而不是拒絕這樣的動作。比如在建立課程表時:
create table course
( …
foreign key(dept_name) references department on delete cascade on update cascade,
…
);
其中,有了on delete cascade 子句,如果刪除department中的元組導致了此參照完整性約束被違反,則刪除並不被系統拒絕,而是對course關係作“級聯”刪除,即刪除參照了被參照關係中刪除元組的元組。有了on update cascade子句,同理,course關係會作“級聯”更新。
SQL 還允許foreign key 子句指明除cascade以外的其他動作,比如:
a. 用set null 代替cascade,表示:如果完整性約束被違反,將參照域置(這裡是dept_name)為空。
b. 用 set default 代替 cascade,表示:如果完整性約束被違反,將參照域置(這裡是dept_name)為域的預設值。
如果存在多個關係的外碼依賴鏈,則在鏈一端所做的刪除或更新可能傳至整個鏈,在此過程中,通過級聯操作未能解決違反約束問題,則系統終止該事務。於是,該事務所做的所有改變及聯級動作將被撤銷。
14. 更為普遍的參照完整性約束形式:複雜check條件與斷言
但是要注意的是,接下來所講述的結構目前還沒有被大多數資料庫系統支援。
在SQL標準定義中,check子句中的謂詞可以是包含子查詢的任意謂詞。於是,可以在關係section上宣告如下所示的參照完整性約束:
check (time_slot_id in (select time_slot_id from time_slot))
這個約束條件不僅在section關係中插入或更新元組時需要檢測,而且在time_slot關係改變時需要被檢測(比如在time_slot關係中刪除元組或更新元組,導致完整性約束被破壞,因此,在time_slot關係中刪除或更新元組時,在section關係需要顯示說明應對方案)。
一個斷言(assertion)就是一個謂詞,它表達了我們希望資料庫始終滿足的一個條件。域約束和參照完整性約束就是斷言的特殊形式。
SQL中的斷言為如下形式:
create assertion <assertion_name>check <predicate>;
舉例:對於student關係中的每個元組,它的屬性tot_cred上的取值必須等於該生所成功修完課程學分的總和。
用斷言描述如下:
createassertion credits_earned_constraint check
(not exists
(select ID
from student
where tot_cred <> (select sum(credit)
from takes natural join course
where student.ID = takes.ID and grade is notnull and grade <> ‘F’
)
)
);
上述採用了“not exists X such that not P(X)”結構來實現約束,因為SQL不提供“for all X, P(X)”結構(其中P是一個謂詞),不過,沒關係,這兩個結構等價。
一些系統開發者省去了對一般性斷言的支援,或者只提供易於檢測的特殊形式的斷言。如果資料庫系統為支援上述複雜的斷言或check子句,如果資料庫支援觸發器的話,可以通過觸發器來實現等價的功能。
練習題:每位老師不能在同一個學期的同一時間段在兩個不同的教師授課,用斷言如何表達?
15. 基本模式定義
建立表(create table 命令)的通用形式:
create table<table_name>
( A1 D1,
A2 D2,
A3 D3,
…,
An Dn,
<完整性約束1>,
…,
<完整性約束n>
);
舉例:
create table teaches
( ID varchar(5),
course_id varchar(8),
sec_id varchar(8),
semester varchar(6),
year numeric(4,0),
primary key (ID, course_id, sec_id,semester, year),
foreign key (course_id, sec_id, semester,year) references section,
foreign key (ID) references instructor
);
刪除表命令:
droptable <table_name>;
修改表命令(向表中新增屬性或刪除屬性):
a. 向表中新增新屬性:
alter table <table_name> add A D;
其中,<table_name>為表名,向該表新增一個屬性A,屬性A的域為D;關係中的所有元組在新屬性上的取值將被置為空null。
向表中新增新約束:
altertable <table_name> add <constraint> ;
當執行新增新約束時,系統首先保證關係滿足指定的約束。如果滿足,那麼約束被施加到關係上;如果不滿足,則拒絕執行上命令。
b. 向表中刪除屬性:
alter table <table_name> dropA;
很多資料庫系統並不支援刪除屬性,儘管如此,它們允許去掉整個表。
16. SQL查詢可以有多種:
1) 單關係查詢
2) 多關係查詢
3) 巢狀子查詢
a. 子查詢巢狀在where子句中
1. 集合成員資格
用連線詞in 和not in,來判斷測試元組是不是集合中的成員。
例如:
select count(distinct ID)
from takes
where(course_id, sec_id, semester, year) in
(selectcourse_id, sec_id, semester, year
from teaches
where teaches.ID = 10101) ;
2. 集合的比較
< some、>some、<= some、 >=some、<>some,其中=some等價於in,然而<>some並不等價於not in。
< all、<=all、>=all、=all、<>all,其中<>all等價於not in,但=all並不等價於in。
3. 空關係測試
SQL提供exists結構用於測試子查詢的結果關係中是否存在元組,用not exists結構測試子查詢結果集中是否不存在元組。若子查詢結果關係中存在元組,則exists結構返回true;否則返回false,而not exists結構返回false,否則返回true。我們可以使用not exists 結構模擬集合包含(即超集)操作:我們可將“關係A包含關係B”寫成“not exists(B except A)”。
舉例1:
select course_id
from section as S
wheresemester = ‘Fall’ and year = 2009 and exists(select * from section as T wheresemester = ‘Spring’ and year = 2010 and T.course_id = S.course_id ) ;
舉例2:找出選修了Biology系開設的所有課程的學生。
selectS.ID, S.name
fromstudent S
where notexists( ( select course_id
from course
where dept_name = ‘Biology’ )
except
( select course_id
from takes as T
where T.ID = S.ID ) ) ;
4. 重複元組存在性測試
SQL提供一個返回布林值的unique結構(此結構尚未被廣泛實現),用於測試在一個子查詢結果中是否存在重複元組。例如:找出所有在2009年最多開設一次的課程,如下所示:
selectT.course_id
fromcourse as T
whereunique (select R.course_id
from course as R
where R.course_id = T.course_id
and R.year= 2009) ;
不使用not unique 結構的一種等價表達形式:
selectT.course_id
fromcourse as T
where 1>= ( select count (R.course_id)
from course as R
where R.course _id = T.course_id
and R.year = 2009 ) ;
b. 子查詢巢狀在from子句中
SQL允許在from子句中使用子查詢表示式。在此採用的主要觀點是:任何select-from-where 表示式返回的結果都是關係,因而可以被插入到另一個select-from-where中任何關係可以出現的位置。
舉例:找出系平均工資超過42000美元的那些系中教師的平均工資:
select dept_name, avg_salary
from ( select dept _name, avg(salary) as avg_salary
from instructor
group bydept_name )
where avg_salary > 42000 ;
或對上述from子句產生的結果關係進行起個名字,並對屬性進行重新命名:
select dept_name , avg_salary
from ( select dept_name, avg(salary)
from instructor
group by dept_name )
as dept_avg (dept_name, avg_salary)
where avg_salary >42000 ;
找出在所有系中工資總額最大的系:
select dept_name, max(tot_salary)
from (select dept_name, sum(salary)
from instructor
group bydept_name)
as dept_total(dept_name , tot_salary)
在2003SQL中允許from子句中的子查詢用關鍵詞lateral作為字首,以便訪問from子句中在它前面的表或子查詢中的屬性。比如:
select name , salary , avg_salary
from instructor S1, lateral(select avg(salary) asavg_salary
frominstructor as S2
whereS2.dept_name = S1.dept_name );
沒有lateral子句的話,子查詢就不能訪問來自外層查詢的相關變數S1。目前只有少數SQL實現支援lateral子句,比如 IBM DB2。
c. 子查詢巢狀在select子句中
舉例:列出所有系以及它們擁有的教師數。
select dept_name , (select count(*)
frominstructor as S2
where S2.dept_name = S1.dept_name) as num_instructors
from department as S1;
d. with 子句
with子句提供定義臨時關係的方法,這個定義只對包含with子句的查詢有效。
比如:
with max_budget( value ) as (select max(budget) fromdepartment )
select budget
from department , max_budget
where department.budget = max_budget.value ;
with子句定義了臨時關係max_budget,此關係在隨後的查詢中馬上被使用了。
例如:假設我們要查詢所有工資總額大於所有系平均工資總額的系,我們利用with子句寫:
with dept_total(dept_name , value) as
(selectdept_name , sum(salary)
frominstructor
group bydept_name),
dept_total_avg (value) as
(select avg(value)
fromdept_total)
select dept_name
from dept_total ,dept_total_avg
where dept_total.value >=dept_total_avg.value;
4) 標量子查詢
舉例:列出所有系以及它們擁有的教師數。
select dept_name , (select count(*)
frominstructor as S2
where S2.dept_name = S1.dept_name) as num_instructors
from department as S1;
上面的例子說明:1. 子查詢時可以使用外層的from子句中的關係的屬性。2. 子查詢保證只返回單個值。
標量子查詢可以出現在select、where和having子句中。當在表示式中使用標量子查詢時,它出現的位置是單個值出現的地方。(儘管標量子查詢的結果型別仍是關係,SQL是從該關係中包含單個屬性的單個元組中取出相應的值,並返回該值。)
5) 相關子查詢
17. 通常查詢結果預設保留重複元組:
select dept_name from instructor;
等價於
select all dept_name from instructor;
如果想強制刪除重複的元組,可在select後加入關鍵字distinct:
select distinct dept_name from instructor;
18. 一個SQL查詢可以包含三種形式的子句:select子句,from子句,where子句。
1) select子句用於列出查詢結果中所需要的屬性。
2) from子句是一個查詢求值中需要訪問的關係列表。
3) where子句是一個作用在from子句中關係的屬性上的謂詞,以篩選from子句產生的結果關係。
想理解一個查詢所代表的運算最容易的方式是以如下順序來考察各子句:首先是from,然後是where,最後是select。
通過from子句定義了一個在該子句中所列出關係上的笛卡爾積。它可以用集合理論來形式化定義,也可以通過下面的迭代過程來理解,為from子句結果關係產生元組:
for each 元組t1 in 關係 r1
for each 元組 t2 in 關係 r2
for each 元組 t3 in 關係 r3
……
for each 元組 tn in 關係 rn
把元組t1,t2,t3,…,tn連線拼成單個元組t
把元組t加入結果關係rfset中
上述程式碼執行完之後,結果關係rfset具有from子句中所有關係的所有屬性,同時結果關係rfset擁有元組數量為m1 *m2*m3*…*mn(其中,mi是關係ri中元組數量)。在該結果關係rfset模式中的屬性名前有關係名作為字首,這是為了避免不同關係具有相同的屬性名。我們在select子句中也可以在多個表中出現相同的屬性名前加上關係名作為字首來避免混淆,而只出現在單個表中的屬性,我們通常去掉關係名字首,以簡化形式。
但是,在實踐中,SQL也許會將上述迭代過程表示式轉換成更高效的等價形式。
19. 一般來說,一個SQL查詢的含義可以理解如下:
1) 為from子句中列出的關係產生笛卡爾積。
2) 在步驟1)的結果上應用where子句中指定的謂詞。
3) 對於步驟2)結果中的每一個元組,輸出select子句中指定的屬性的值(或表示式的結果)。
20. SQL還支援其他一些附加的基本運算:
1) 更名運算
可以重新命名結果關係中屬性的方法,如下形式的as子句:
old_name asnew_name
上述的as子句不僅可以在select子句中出現,也可以在from子句中出現。
重新命名一般有兩個用途:
a. 將一個長的關係名稱(或select子句屬性)替換為較短的名稱,這樣方便使用。
b. 如果需要比較同一個關係中的元組的情況,則必須對關係重新命名,例如:
select distinct T.name
from instructor as T, instructor as S
where T.salary > S.salary and S.dept_name = ‘Biology’;
其中,T 和S可以被認為是instructor關係的兩份拷貝,準確的說是別名,表別名,相關名稱,相關變數,等都行。
2) 字串運算
a. SQL字串使用一對單引號表示,如果單引號作為字串的一部分時,那就用兩個單引號字元來表示。
百分號(%):匹配任意子串。
下劃線(_):匹配任意一個字元。
b. 轉義字元用法
在like 運算中使用escape關鍵字來定義轉義字元,轉義字元直接放在特殊字元前面。例如1:like ‘ab\%cd%’ escape ‘\’
上面將第一個特殊字元%作為字串的組成部分,’\’作為轉義字元,所以,含義是匹配所有以ab%cd開頭的任意字串。
例如2:like ‘ab\\cd%’ escape ‘\’ 匹配所有以“ab\cd”開頭的字串。
c. select 子句中的屬性說明
星號(*)在select子句中代表“所有的屬性”。
d. 排列元組的顯示次序
使用order by 子句:select name from instructor where dept_name = ‘Physics’ order byname;
order by <attribute_name>子句預設使用升序。與預設等價的是order by <attribute_name> asc,我們可以用desc表示降序。比如:
select * from instructor order by salary desc, name asc ;含義是以屬性salary作為第一級排序(降序),以屬性name作為第二級排序(升序)。
e. where 子句謂詞
SQL提供between…and…,或not between比較運算。
21. 集合運算
union、intersect和except運算分別對應於數學集合論中的∪、∩和-運算。
1) union 運算
( select course_id
from section
where semester = ‘Fall’and year = 2009
)
union
(select course_id
from section
where semester = ‘Spring’and year = 2010
);
union運算自動去掉重複元組。如果想保留,可以用union all 代替union。
2) intersect 運算
( select course_id
from section
where semester = ‘Fall’ and year = 2009
)
intersect
(select course_id
from section
where semester = ‘Spring’and year = 2010
);
intersect運算在最終結果關係中自動去掉重複元組(預設的)。如果想保留,可以用intersect all 代替intersect。比如,在使用了intersect all 時,如果存在這樣的情況:ECE-101在2009年秋季學期開設了4個課程段,在2010年春季學期開設了2個課程段,那麼在結果關係中有2個ECE-101元組;若使用intersect時,結果關係只有1個ECE-101元組。
3) 差運算
( select course_id
from section
where semester = ‘Fall’and year = 2009
)
except
( select course_id
from section
where semester = ‘Spring’and year = 2010
);
except 運算從其第一個輸入中輸出所有不出現第二個輸入中的元組,此運算在執行差操作之前自動去除輸入中重複元組(預設的)。比如,ECE-101在2009年秋季學期開設了4個課程段,在2010年春季學期開設了2個課程段,那麼except運算的結果關係中就只有1個ECE-101元組。如果想在結果關係中出現2個ECE-101元組,可以用except all 代替except。用except all能夠保留下重複元組,前提是相減結果為正。若為負,在結果關係中沒有任何關於這個元組了(這裡是ECE-101)。
22. 空值
1) 空值與算術運算子,當空值參與算術表示式運算中,運算結果為空。
2) 空值與比較運算子,當空值參與比較表示式運算中, 運算結果為unknown(既不是謂詞is null,也不是謂詞is notnull),它是除了true和false之外的第三個邏輯詞。特別地,not unknown 的結果為unknown。
3) 空值與集合運算子
當一個查詢使用select distinct 子句時,重複元組將會被去除,重複的判斷依據:在兩個元組對應的屬性值上,都是非空並且值相等,或者都是空。比如,{(‘A’,null),(‘A’,null)},這兩個元組被認為是相同的,即使在某些屬性上存在空值。
注意:上述對待空值的方式與謂詞中對待空值的方式不同,在謂詞中null = null會返回unknown,而不是true。(總結:在謂詞中,兩個空null被認為是兩個不相同的東西,在篩選元組時,兩個空被認為時相同的東西)
23. 聚集
1) 基本聚集
有avg()、sum()、count()、min()、max()五個基本聚集,avg和sum的輸入必須是數字集,但其他運算子還可以在非數字資料型別的集合上,如字串。
常用形式舉例:avg(salary)、count(distinct ID)、count(*)
2) 分組聚集
a. 用group by 子句進行分組。groupby子句中給出的一個或多個屬性是用來構造分組的。分組的依據:在group by 子句中的所有屬性上的取值相同的元組將被分在一個組中。在沒有用group by子句的查詢中,預設整個關係被當做一個分組,比如,select avg(salary) from instructor 。
當查詢語句出現聚集函式又有group by時,執行過程:先分組,後計算。
注意:當查詢使用分組時,任何沒有出現在group by子句中的屬性如果出現在select子句中的話,它只能出現在聚集函式內部,否則這樣的查詢就是錯誤的。
b. 對各個分組進行篩選,使用having子句
having 子句中的謂詞在形成分組後才能起作用。having子句與where子句的區別:having子句用於對分組限定條件,而where子句用於對元組限定條件。
舉例:
select dept_name avg(salary) as avg_salary
from instructor
group by dept_name
having avg(salary) >42000 ;
c. 當查詢語句出現分組聚集函式、where子句、group by子句或having子句時,通過下述操作序列來定義理解:
5. 最先根據from子句來產生一個關係。
6. 如果有出現了where子句,where子句的謂詞將運用於from子句的結果關係上。
7. 如果出現了group by子句,滿足where子句的元組通過group by子句形成分組。如果沒有group by子句,則將滿足where子句謂詞的整個元組被當作為一個分組。
8. 如果出現了having子句,它將應用到每個分組上;不滿足having子句謂詞的分組將被拋棄。
9. select子句利用剩下的元組產生出查詢結果中的元組,也就是在每個分組上應用聚集函式來得到單個結果元組。
舉例:
select course_id , semester ,year, sec_id, avg(tot_cred)
from takes natural join student
where year =2009
group by course_id , semester, year, sec_id
having count(ID) >= 2 ;
3) 對空值和布林值的聚集
a. 空值對聚集的影響
聚集函式根據以下原則處理空值:除了count(*)外所有的聚集函式都忽略輸入集合中的空值。
聚集函式根據以下原則處理空集:空集的count運算值為0,而其他所有聚集運算在輸入值為空值的情況下返回一個空值。
b. 布林值對聚集的影響
能處理布林值(true、false、unknown)的聚集函式有some和every。(在SQL:1999中引入了布林資料型別,同時提供處理布林資料型別的聚集函式)。
24. 資料庫的修改
1) 刪除
delete from r where P;
其中P代表一個謂詞,r代表一個關係。
2) 插入
insert into course values( ‘CS-437’,’Database System’,’Comp.Sci’,4);
在上述例子中,元組屬性值的排列順序和關係模式中屬性排列的順序一致。
下面在insert語句中指定屬性:
insert into course (course_id , title , dept_name, credits) value (‘CS-437’,’Database System’,’Comp.Sci’,4) ;
下面以查詢結果的基礎上插入元組:
insert into instructor
select ID, name, dept_name, 18000
from student
where dept_name= ‘Music’ and tot_cred >144 ;
3) 更新
舉例1:
update instructor
set salary = salary * 1.05;
where salary < (select avg(salary) from instructor) ;
舉例2:
假設工資超過100000美元的教師漲3%的工資,其餘教師的工資漲5%。
update instructor
set salary = salary * 1.03;
where salary > 100000;
update instructor
set salary = salary *1.05;
where salary <100000;
注意上面兩條update語句的順序十分重要。
SQL提供case結構,我們可以利用它在一條update語句中執行前面的兩種更新,避免更新錯誤引發的問題:
update instructor
set salary = case
whensalary <= 100000 then salary * 1.05
elsesalary *1.03
end
case語句的一般格式如下:
case
when pred1 then result1 ;
when pred2 then result2 ;
when pred3 then result3 ;
…
when predn then resultn ;
else result0
end
case 語句可以用在任何應該出現值的地方。
考慮這樣的更新:我們把每一student元組的tot_cred屬性值設定為該生成功學完的課程學分的總和。
update student S
set tot_cred = ( select sum(credits)
from takes natural join course
where S.ID = takes.ID and takes.grade <> ‘F’ and takes.grade isnot null
);
如果一個學生沒有成功學完任何課程,上述更新語句將其tot_cred屬性值設定為空。如果想把這樣的屬性值設定為0的話,我們可以使用另一條update語句來把空值替換為0。更好的解決方案是把上述子查詢中的“select sum(credits)”子句替換為如下使用case表示式的select子句:
select case
whensum(credits) is not null then sum(credit)
else 0
end
所以:
update student S
set tot_cred =(
select case
whensum(credits) is not null then sum(credit)
else 0
end
from takesnatural join course
where S.ID = takes.ID and takes.grade<> ‘F’ and takes.grade is not null
);
25. 連線表示式
SQL連線條件有以下幾種:
1) using條件連線,比如r1 join r2using (A1, A2),連線匹配:r1.A1 = r2.A1 且 r1.A2 = r2.A2。
2) on條件連線,比如r1 join r2 onr1.A1 = r2.A1, r1.A2 = r2.A2; on條件連線比using條件連線更靈活。on條件謂詞的寫法與where子句謂詞類似。
3) natural自然連線,比如 r1 natural join r2,含義:在r1和r2兩個關係模式中都出現的屬性上取值相同的元組對連線起來合為單個元組。連線結果顯示順序:先列出共同屬性的值,然後再列出第一個關係模式屬性的值,最後第二個關係模式屬性的值。
SQL連線型別大體上分為兩種:
1) 內連線:對連線的兩個關係中,不滿足連線匹配條件的元組全部“丟棄”,只保留滿足條件的元組。使用關鍵字inner,此關鍵字可選,也就是預設的連線是內連線(…inner join …)。比如,natural inner join,
2) 外連結:與內連線對應,將內連線“丟棄”的元組保留下來,根據保留的情況可以分為左外連線(left outer join),右外連線(right outer join)和全外連線(full outer join)。使用關鍵字outer。
注意:任意的連線形式可以和任意的連線條件進行組合。也就是,內連線和外連結都可以使用上述3種條件連線(using、on和natural)。
內連線包括:
1) 自然連線
a. 一般自然連線
select name, course_id
from instructor natural join teaches ;
等價於
select name, course_id
from instructor, teaches
where instructor.ID = teaches.ID ;
b. 構造形式的自然連線
select name, title
from (instructor natural join teaches ) join courseusing(course_id) ;
兩個關係中共同屬性中的一個(course_id)作為連線條件,其他的共同屬性則不必相等。
外連線包括:
1) 左外連線
select *
from student natural left outer jointakes ;
其中,關鍵字natural指定了連線條件(也就是共同屬性上值相等)。
select *
from student left outer join takes onstudent.ID = takes.ID ;
上面的查詢語句執行結果與下面的查詢語句執行結果是一樣的。從這兩句中可以體會on 和where在外連線中的表現是不同的:
select*
from student left outer jointakes on true
where student.ID = takes.ID ;
其中連線條件為true,也就是student與takes作笛卡爾乘積。然後在from子句結果關係中通過where子句篩選出滿足student.ID = takes.ID的元組。
2) 右外連線
select *
from takes natural right outer joinstudent ;
3) 全外連線
select *
from (select *
from student
where dept_name= ‘Comp.Sci’)
natural fullouter join
(select *
from takes
where semester =‘Spring’ and year = 2009 ) ;
26. 檢視
SQL允許通過查詢來定義“虛關係”,它在概念上包含查詢的結果。虛關係並不預先計算並存儲,而是在使用虛關係的時候才通過執行查詢被計算出來。
任何像這種不是邏輯模型的一部分,但作為虛關係對使用者可見的關係稱為檢視(view)。在任何給定的實際關係集合上能夠支援大量檢視。
1) 檢視定義
create view v as<query expression> ;
其中<query expression>可以是任何合法的查詢表示式,v表示檢視名。
create view physics_full_2009 as
selectcourse.course_id, sec_id, building, room_number
from course,section
wherecourse.course_id = section.course_id
and course.dept_name = ‘Physics’
andsection.semester = ‘Fall’
andsection.year = 2009 ;
2) SQL查詢中使用檢視
一旦定義了一個檢視,我們就可以用檢視名指代該檢視生成的虛關係。
select course_id
from physics_full_2009
where building = ‘Watson’ ;
檢視的屬性可以按下述方式顯示指定:
create view physics_full_2009 (coursed,secId,building,roomNumber) as
selectcourse.course_id, sec_id, building, room_number
from course,section
wherecourse.course_id = section.course_id
and course.dept_name = ‘Physics’
andsection.semester = ‘Fall’
andsection.year = 2009 ;
3) 物化檢視
特定資料庫系統允許儲存檢視關係,但是它們保證:如果用於定義檢視的實際關係改變,檢視也要跟著修改。這樣的檢視被稱為物化檢視(materialized view)。
為了保持物化檢視一直在最新狀態的過程稱為物化檢視維護(materialized view maintenance ),或者通常簡稱檢視維護(viewmaintenance)。
檢視維護方式:
a. 實際關係改變時,立即進行檢視維護
b. 訪問檢視時,進行檢視維護。
c. 進行週期性檢視維護。
物化檢視的特點:
a. 優點:查詢時可以快速響應,避免讀取大量底層關係。
b. 缺點:需要付出儲存代價和更新開銷。
4) 檢視更新
對於查詢而言,檢視是一個有用的工具。但是,對檢視的更新、插入和刪除將帶來更嚴重的問題。一般說來,如果定義檢視的查詢對下列條件都能滿足,我們稱SQL檢視是可更新的(updatable)(即檢視上可以進行插入、更新或刪除):
a. from子句中只有一個數據庫關係。
b. select子句中只包含關係的屬性名,不包含任何表示式、聚集或distinct宣告。
c. 任何沒有出現在select子句中的屬性可以取空值,即這些屬性上沒有not null 約束,也不構成主碼的一部分。
d. 查詢中不含有group by 或having子句。
在這些限制下,下面的檢視允許執行update、insert和delete操作:
create viewhistory_instructors as
select *
frominstructor
where dept_name = ‘History’;
可以對history_instructors中進行更新、插入和刪除。假設使用者嘗試向檢視中插入元組( ‘25566’,’Brown’,’Biology’,100000),這個元組可以被插入,但是不滿足檢視所要求的選擇條件,所以它不會出現在檢視history_instructors中。為了解決這個問題,可以在檢視定義末尾加上with check option子句。
27. 事務(transaction)由查詢或更新語句(包括插入、刪除和更新操作)的序列組成。SQL標準規定當一條SQL語句被執行,就隱式地開始了一個事務。而結束一個事務由下面任何一件事情發生:
1) Commit work :提交當前事務,也就是將該事務所做的更新在資料庫中持久儲存。說明該事務成功完成所有步驟。在事務被提交後,一個新的事務自動開始。在某種意義上,事務提交就像對編輯文件的變化存檔,而回滾就像不儲存變化退出編輯。
2) Rollback work :回滾當前事務,即撤銷該事務中所有SQL語句對資料庫的更新。這樣,資料庫就恢復到執行該事務第一句之前的狀態。
上面兩句中的關鍵字work都是可選的。
一個事務或者在完成所有步驟後提交其行為,或者在不能成功完成其所有動作的情況下回滾其所有動作,通過這種方式資料庫提供了對事務具有原子性(atomic)的抽象,原子性也就是不可分割性。
在很多SQL實現中,預設方式下每個SQL語句自成一個事務,且一執行完就提交。如果一個事務要執行多條SQL語句,就必須關閉單獨SQL語句的自動提交,如何關閉也依賴於特定的SQL實現。
作為SQL:1999標準的一部分(但目前只有一些SQL實現支援),允許多條SQL語句包含在關鍵字begin atomic ……end 之間。所有在關鍵字之間的語句構成了一個單一事務。
28. 完整性約束
保證授權使用者對資料庫所做的修改不會破壞資料的一致性。
1) 單個關係上的約束
2) 參照完整性約束
3) 複雜check條件與斷言
29. 建立索引
在關係屬性上建立索引(index)是一種資料結構,它可以高效地找到關係中那些在索引屬性上取值給定的元組,而不用掃描關係中的所有元組。
儘管SQL語言沒有給出建立索引的正式語法定義,但很多資料庫都支援使用如下所示的語法來建立索引:
createindex studentID_index on student(ID) ;
上述語句在student關係的屬性ID上建立了一個名為studentID_index的索引。當要查詢ID為22201的student元組時,SQL查詢處理器就會使用上面定義的studentID_index索引來找到所需的元組,而不用讀取整個關係。
30. 關係模式中的碼的概念同樣適用於實體集和聯絡集。不管聯絡集R中有沒有其他的屬性,聯絡集中所有的外碼構成一個屬性集合是該聯絡集的超碼。