前言
- 本篇文章學習書籍:《數據庫系統概論》第5版 王珊 薩師煊編著
- 視頻資源來自:數據庫系統概論完整版(基礎篇+高級篇+新技術篇)
- 由於 BitHachi 學長已經系統的整理過本書了,我在學習課本和視頻以及學長文章的同時在學長文章的基礎上進行相應學習修改。(學長原系列目錄:Here)
- 資料參考網站:MySQL教程
0.思維導圖

1.數據庫完整性概述
簡單介紹:
-
首先先概述一下數據庫完整性指的是什么,
數據庫完整性指的是數據的正確性和相容性。 -
數據的
正確性是指數據是符合現實世界語義、反映當前實際狀況的;比如說人類的性別,只能是男和女。 -
數據的
相容性是指數據庫同一對象在不同關系表中的數據是符合邏輯的。比如說年齡一般都在1-100歲,當然也有超過一百歲的,反正沒有兩百歲,三百歲成仙的人類。
既然我們學的是數據庫,那么數據庫管理系統就應該為數據完整性實現如下的功能:
1.提供定義完整性約束條件的機制
- 完整約束條件也稱
完整性規則,是數據庫中數據必須滿足的語義條件規則 - 為保證數據的正確、有效和相容性的一些規則
- 數據的主碼、外碼、一些約束規則
2.提供完整性檢查的方法
- 數據庫管理系統中檢查數據是否滿足完整性規則的機制稱為
完整性檢查 - 一般在執行INSERT、UPDATE、DELETE時檢查
3.違約處理
- 數據庫管理系統若發現用戶的操作違背了完整性約束條件將采取一定的動作,如拒絕(NO ACTION)執行該操作或級聯(CASCADE)執行其他操作,進行違約處理以保證數據的完整性。
此前寫的一篇文章提到了關系完整性約束的基本概念 關系完整性的基本概念,而本篇文章講的是利用SQL如何去實現這些約束機制,如何實現完整性規則
2.實體完整性—PRIMARY KEY
(1)實體完整性的定義
關系模型的實體完整性
- CREATE TABLE中用PRIMARY KEY定義
單屬性構成的碼有兩種說明方法
- 定義為列級約束條件
- 定義為表級約束條件
對多個屬性構成的碼只有一種說明方法
- 定義為表級約束條件
舉幾個例子
將Student表中的Sno屬性定義為碼
(1)在列級定義主碼
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY,
Sname CHAR(20) NOT NULL,
Ssex CHAR(2) ,
Sage SMALLINT,
Sdept CHAR(20));
(2)在表級定義主碼
CREATE TABLE Student
(Sno CHAR(9),
Sname CHAR(20) NOT NULL,
Ssex CHAR(2) ,
Sage SMALLINT,
Sdept CHAR(20),
PRIMARY KEY (Sno)
);
將SC表中的Sno,Cno屬性組定義為碼
CREATE TABLE SC
(Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT,
PRIMARY KEY (Sno,Cno) /*只能在表級定義主碼*/
);
(2)實體完整性檢查和違約處理
插入或對主碼列進行更新操作時,RDBMS按照實體完整性規則自動進行檢查。包括:
- 檢查主碼值是否唯一,如果不唯一則拒絕插入或修改
- 檢查主碼的各個屬性是否為空,只要有一個為空就拒絕插入或修改
檢查記錄中主碼值是否唯一的一種方法是進行全表掃描

-
全表掃描是十分耗時的。為了避免對基本表進行全表掃描,關系數據庫管理系統一般 都在主碼上
自動建立一個索引,如圖5.2的B+樹索引,通過索引查找基本表中是否已經存在新的主碼值將大大提高效率。 -
例如,如果新插入記錄的主碼值是25,通過主碼索引,從B+樹的根結點開始查找,只要讀取三個結點就可以知道該主碼值已經存在,所以不能插入這條記錄。這三個結點是根結點(51)、中間結點(1230)和葉結點(15 20 25)。

2.參照完整性—REFERENCES
(1)參照完整性定義
關系模型的參照完整性定義
- 在CREATE TABLE中用
FOREIGN KEY短語定義哪些列為外碼 - 用
REFERENCES短語指明這些外碼參照哪些表的主碼
舉個例子
例如,關系SC中一個元組表示一個學生選修的某門課程的成績,
(Sno,Cno)是主碼。
Sno,Cno分別參照引用Student表的主碼和Course表的主碼
定義SC中的參照完整性
CREATE TABLE SC
(
Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT,
PRIMARY KEY (Sno, Cno), /*在表級定義實體完整性*/
FOREIGN KEY (Sno) REFERENCES Student(Sno),
/*在表級定義參照完整性*/
FOREIGN KEY (Cno) REFERENCES Course(Cno)
/*在表級定義參照完整性*/
);
(2)參照完整性檢查和違約處理

參照完整性違約處理
- 拒絕(NO ACTION)執行
默認策略 - 級聯(CASCADE)操作
- 設置為空值(SET-NULL)
對於參照完整性,除了應該定義外碼,還應定義外碼列是否允許空值
[例4] 顯式說明參照完整性的違約處理示例
CREATE TABLE SC
(
Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT,
PRIMARY KEY(Sno,Cno),
FOREIGN KEY (Sno) REFERENCES Student(Sno)
ON DELETE CASCADE /*級聯刪除SC表中相應的元組*/
ON UPDATE CASCADE, /*級聯更新SC表中相應的元組*/
FOREIGN KEY (Cno) REFERENCES Course(Cno)
ON DELETE NO ACTION
/*當刪除course 表中的元組造成了與SC表不一致時拒絕刪除*/
ON UPDATE CASCADE
/*當更新course表中的cno時,級聯更新SC表中相應的元組*/
);
- 經過測試,當UPDATE更新Student和Course表數據時,SC也自動更新
- 當刪除Student的數據時,SC同步刪除相應數據
- 當刪除Course的數據時,拒絕刪除,因為SC中有相應的外碼數據,並設置了NO ACTION
- 當刪除SC的數據時,對Student和Course無影響


3.用戶定義的完整性—CHECK
- 用戶定義的完整性就是針對
某一具體應用的數據必須滿足的語義要求 - RDBMS提供,而不必由應用程序承擔
(1)屬性上的約束條件定義
CREATE TABLE時定義
- 列值非空(NOT NULL)
- 列值唯一(UNIQUE)
- 檢查列值是否滿足一個布爾表達式(CHECK)
1.不允許取空值
[例5] 在定義SC表時,說明Sno、Cno、Grade屬性不允許取空值。
CREATE TABLE SC
(
Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT NOT NULL,
PRIMARY KEY (Sno, Cno),
/* 如果在表級定義實體完整性,隱含了Sno,Cno不允許取空值,
則在列級不允許取空值的定義就不必寫了 */
);
2.列值唯一
[例6]建立部門表DEPT,要求部門名稱Dname列取值唯一,
部門編號Deptno列為主碼
CREATE TABLE DEPT
(
Deptno NUMERIC(2),
Dname CHAR(9) UNIQUE,/*要求Dname列值唯一*/
Location CHAR(10),
PRIMARY KEY (Deptno)
);
3. 用CHECK短語指定列值應該滿足的條件
[例7]Student表的Ssex只允許取“男”或“女”。
CREATE TABLE Student
(
Sno CHAR(9) PRIMARY KEY,
Sname CHAR(8) NOT NULL,
Ssex CHAR(2) CHECK (Ssex IN (‘男’,‘女’) ) ,
/*性別屬性Ssex只允許取'男'或'女' */
Sage SMALLINT,
Sdept CHAR(20)
);
(2)屬性上的約束條件檢查和處理
- 插入元組或修改屬性的值時,RDBMS檢查屬性上的約束條件是否被滿足
- 如果不滿足則操作被拒絕執行
(3)元組上的約束條件的定義
- 在CREATE TABLE時可以用
CHECK短語定義元組上的約束條件,即元組級的限制 - 同屬性值限制相比,元組級的限制可以設置不同屬性之間的取值的相互約束條件
[例9] 當學生的性別是男時,其名字不能以Ms.打頭。
CREATE TABLE Student
(
Sno CHAR(9),
Sname CHAR(8) NOT NULL,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20),
PRIMARY KEY (Sno),
CHECK (Ssex='女' OR Sname NOT LIKE 'Ms.%')
/*定義了元組中Sname和 Ssex兩個屬性值之間的約束條件*/
);
性別是女性的元組都能通過該項檢查,因為Ssex=‘女’成立;
當性別是男性時,要通過檢查則名字一定不能以Ms.打頭
(4)元組上的約束條件檢查和違約處理
- 插入元組或修改屬性的值時,RDBMS檢查元組上的約束條件是否被滿足
- 如果不滿足則操作被拒絕執行
4.完整性約束命名子句—CONSTRAINT
CONSTRAINT 約束語句格式:
CONSTRAINT <完整性約束條件名>
[PRIMARY KEY短語
|FOREIGN KEY短語
|CHECK短語]
舉個例子:
[例10] 建立學生登記表Student,要求學號在90000~99999之間,
姓名不能取空值,年齡小於30,性別只能是“男”或“女”。
CREATE TABLE Student
(Sno NUMERIC(6)
CONSTRAINT C1 CHECK (Sno BETWEEN 90000 AND 99999),
Sname CHAR(20)
CONSTRAINT C2 NOT NULL,
Sage NUMERIC(3)
CONSTRAINT C3 CHECK (Sage < 30),
Ssex CHAR(2)
CONSTRAINT C4 CHECK (Ssex IN ( '男','女')),
CONSTRAINT StudentKey PRIMARY KEY(Sno)
);
在Student表上建立了5個約束條件,包括主碼約束(命名為StudentKey)
以及C1、C2、C3、C4四個列級約束。
這個沒有C2應該是為主鍵就忽略沒顯示叭

修改表中的完整性限制
- 使用ALTER TABLE語句修改表中的完整性限制
[例13] 修改表Student中的約束條件,要求學號改為在900000~999999之間,
年齡由小於30改為小於40
可以先刪除原來的約束條件,再增加新的約束條件
ALTER TABLE Student
DROP CONSTRAINT C1;
ALTER TABLE Student
ADD CONSTRAINT C1 CHECK (Sno BETWEEN 900000 AND 999999);
ALTER TABLE Student
DROP CONSTRAINT C3;
ALTER TABLE Student
ADD CONSTRAINT C3 CHECK (Sage < 40);

5.域中的完整性限制—DOMAIN
關於域的定義有些數據庫可能不同,或者定義失敗,得觀看相關的手冊深入學習,但是SQL中是有定義DOMAIN,初學先了解一下叭。
SQL支持域的概念,並可以用CREATE DOMAIN語句建立一個域以及該域應該滿足的完整性約束條件。
[例14]建立一個性別域,並聲明性別域的取值范圍
CREATE DOMAIN GenderDomain CHAR(2)
CHECK (VALUE IN ('男','女') );
這樣[例10]中對Ssex的說明可以改寫為Ssex GenderDomain
[例15]建立一個性別域GenderDomain,並對其中的限制命名
CREATE DOMAIN GenderDomain CHAR(2)
CONSTRAINT GD CHECK ( VALUE IN ('男','女') );
[例16]刪除域GenderDomain的限制條件GD。
ALTER DOMAIN GenderDomain
DROP CONSTRAINT GD;
[例17]在域GenderDomain上增加限制條件GDD。
ALTER DOMAIN GenderDomain
ADD CONSTRAINT GDD CHECK (VALUE IN ( '1','0') );
通過[例16]和[例17],就把性別的取值范圍由('男','女')改為 ( '1','0')
由於博主考試內容不含斷言和觸發器,所以這兩個部分不做介紹
