數據庫完整性
實體完整性
-
實體完整性:
PRIMARY KEY
- 列級 約束條件
CREATE TABLE Student (Sno CHAR(9) PRIMARY KEY, /* 在列級定義主碼 */ Sname CHAR(20) NOT NULL, Ssex CHAR(2), Sdept CHAR(20) );
- 表級約束條件
CREATE TABLE Student (Sno CHAR(9), Sname CHAR(20) NOT NULL, Sage SMALLINT, Sdept CHAR(20), PRIMARY KEY (Sno) /* 表級定義主碼 */ )
- 多個屬性構成主碼 表級約束條件
CREATE TABLE SC (Sno CHAR(9) NOT NULL, Cno CHAR(4) NOT NULL, Grade SMALLINT, PRIMARY KEY (Sno,Cno) /* 只能在表級定義主碼 */ )
-
實體完整性檢查和違約處理
- 檢查主碼值是否唯一,如果不唯一則拒絕插入或者修改
2.檢查主碼的各個屬性是否為空,只要有一個為空就拒絕插入或修改
- 檢查主碼值是否唯一,如果不唯一則拒絕插入或者修改
-
參照完整性
FOREIGN KEY
外碼CREATE TABLE SC (Sno CHAR(9) NOT NULL, Cno CHAR(4) NOT NULL, Grade SNALLINT, PRIMARY KEY (Sno,Cno), /* 表級定義實體完整性 */ FOREIGN KEY (Sno) REFERENCES Student(Sno), /* 表級定義參照完整性 */ FOREIGN KEY (Cno) REFERENCES Course(Cno) /* 表級定義參照完整性 */ )
-
參照完整性檢查和違約處理
被參照表(如:Student) 參照表(如:SC) 違約處理 可能破壞參照完整性 <--插入元祖 拒絕 可能破壞參照完整性 <--修改外碼值 拒絕 刪除元祖 --> 可能破壞參照完整性 拒絕/級聯/設置空值 修改主碼值 --> 可能破壞參照完整性 拒絕/級聯/設置空值 可能破壞參照完整性的情況及違約處理
被參照表(如:Student) 參照表(如:SC) 違約處理 可能破壞參照完整性 <--插入元祖 拒絕 可能破壞參照完整性 <--修改外碼值 拒絕 刪除元祖 --> 可能破壞參照完整性 拒絕/級聯/設置空值 修改主碼值 --> 可能破壞參照完整性 拒絕/級聯/設置空值 拒絕 (NO ACTION) 執行
不允許該操作執行, 該策略一般設置為默認策略級聯 (CASCADE) 操作
當刪除或修改被參照表(Student)的一個元祖造成了與參照表(SC)的不一致,則刪除或修改參照表中的所有造成不一致的元祖-
設置為空值( SET - NULL)
當刪除或修改被參考表的一個元祖時造成了不一致,則將參照表中的所有造成不一致的元祖的對應屬性設置為空值。顯式說明參照完整性違約處理示例
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 CASECADE /* 當刪除 student 表匯總的元祖時,級聯刪除 SC 表中相應的元祖 */ ON UPDATE CASECADE, /* 當更新 studnet 表中的 sno 時, 級聯更新 SC 表中相應的元祖 */ FOREIGN KEY(Cno) REFERENCES Course(Cno) /* 在表級定義參照完整性 */ ON DELETE NO ACTION /* 當刪除 course 表中的元祖造成了與 SC 表不一致時拒絕刪除 */ ON UPDATE CASCADE /* 當更新 course 表中的 cno 時, 級聯更新 SC 表中相應的元祖 */ );
-
用戶定義完整性
-
屬性上的約束條件的定義
- 列值非空 (NOT NULL)
- 列值唯一 (UNIQUE)
- 檢查列值 是否 滿足一個布爾表達式 (CHECK)
- 不允許取空值
CREATE TABLE SC (Sno CHAR(9) NOT NULL, /* Sno 屬性不允許取空值 */ Cno CHAR(4) NOT NULL, /* Grade 屬性不允許為空 */ Grade SMALLINT NOT NULL, /* Grade 屬性不允許取空值 */ PRIMARY KEY (Sno, Cno) /* 如果在表級定義實體完整性,隱含了 Sno,Cno不允許取空值則在列級不允許取空值的定義就不必寫了 */ )
- 列唯一
CREATE TABLE DEPT ( Deptno NUMERIC(2), Dname CHAR(9) UNIQUE, /* 要求 Dname列唯一 */ Location CHAR(10), PRIMARY KEY(Deptno) )
- 用 CHECK 短語指定列值應該滿足的條件
CREATE TABLE Student (Sno CHAR(9) PRIMARY KEY, /* 在列級定義主碼 */ Sname CHAR(8) NOT NULL, /* Sname 屬性不允許取空值 */ Ssex CHAR(8) CHECK (Ssex IN ('男','女')) /* 性別屬性Ssex 只允許取'男'或'女' */ Sage SMALLINT, Sdept CHAR(20) )
SC 表的GRADE 的值在0到100之間
CREATE TABLE SC (Sno CHAR(9) NOT NULL, Cno CHAR(4) NOT NULL, Grade SMALLINT CHECK (Grade >=0 AND Grade <= 100), PRIMARY KEY (Sno,Cno), FOREIGN KEY (Sno) REFERENCES Studnet(Sno), FOREIGN KEY (Cno) REFERENCES Course(Cno) )
屬性上的約束條件檢查和違約處理
-
元祖上的約束條件的定義
當學生的性別是男時,名字不能以 Ms 開頭CREATE TABLE Student (Sno CHAR(9), Sname CHAR(8) NOT NULL, Ssex CHAR(2), Sage SMALLINT, PRIMARY KEY (Sno), CHECK (Ssex='女' OR Sname NOT LIKE 'Ms.%') /* 定義了元組中Sname 和 Ssex 兩個屬性值之間的約束條件 */ ):
元組上的約束條件檢查和違約處理
當往表中插入元組或修改屬性的值時,RDBMS就檢查元組上的約束條件是否被滿足,如果不滿足則操作被拒絕執行
-
-
完整性命名子句
- 完整性約束命名子句
CONSTRAINT <完整性約束條件名> [PRIMARY KEY短語|FOREIGN KEY 短語|CHECK短語]
例: 建立學生登記表 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)
)
創建了 5 個約束 C1,C2,C3,C4 StudentKey。
例:建立教師表TEACHER 要求每個教師的應發工資不低于 3000元 應發工資實際上就是實發工資列 Sal 與 扣除 項 Deduct 之和。
CREATE TABLE TEACHER
(Eno NUMERIC(4) PRIMARY KEY,
Ename CHAR(10),
Job CHAR(8),
Sal NUMERIC(7,2),
Deduct NUMERIC(7.2),
Deptno numeric(2),
CONSTRAINT EMPFKey FOREIGN KEY (Deptno) REFERENCES DEPT(Deptno),
CONSTRAINTS C1 CHECK(Sal + Deduct >= 3000)
);
-
修改表中的完整性限制
解除表 Student 中 性別限制ALTER TABLE Student DROP CONSTRAINT C4
修改表 Student 中 的約束條件, 要求學號改為 900000-999999 之間,年齡由小于30 改為小于 40.
先刪除原來的約束條件,再增加新的約束條件
ALTER TABLE Student Drop CONSTRAINT C1; ALTER TABLE Student ADD CONSTRAINT C1 CHECK (Sno BETWEEN 9000 000 AND 999 999), ALTER TABLE Student DROP CONSTRAINT C3; ALTER TABLE Student ADD CONSTRAINT C3 CHECK( Sage < 40 );
-
域中的完整性限制
CREATE DOMAIN 名字 類型 CHECK語句
例: 建立一個性別域,并聲明性別域的取值范圍
CREATE DOMAIN GenderDemain CHAR(2) CHECK(VALUE IN ('男','女'));
例:建立一個性別域 GenderDomain,并對其中的限制命名
CREATE DOMAIN GenderDomain CHAR(2) CONSTRAINT GD CHECK (VALUE IN ('男','女'));
例: 刪除域 GenderMain 的限制條件 GD
ALTER DOMAIN GenderDomian DROP CONSTRAINT GD;
例:在域GenderDomian 上增加限制條件 GDD
ALTER DOMAIN GenderDomian ADD CONSTRAINT GDD CHECK (VALUE IN ('1','0'));
觸發器 Trigger
-
定義觸發器
CREATE TRIGGER <觸發器名字> |BEFORE|AFTER| <觸發器事件> ON <表名> FOR EACH |ROW |STATEMENT| [WHEN <觸發條件>] 觸發動作體
1.誰可以創建觸發器?
表的創建者
2. 一張表可以創建無數個觸發器么?
只能創建有限個觸發器
3. 和觸發器關聯的表 稱為目標表
4. 觸發事件怎么理解?
觸發事件可以是 INSERT/DELETE/UPDATE 也可以是這幾個事件的組合,如 INSERT OR DELETE 等, UPDATE 后面還可以有 OF<觸發列...> ,即進一步指明修改哪些列時,觸發器激活。
5. 觸發器的類型
觸發器按照所觸發動作的間隔尺寸可以分為行級觸發器(FOR EACH ROW) 和 語句級觸發器(FOR EACH STATEMENT).
FOR EACH ROW 凡是該row 的值發生變化,就會觸發,觸發多次
FOR EACH STATEMENT 無論多少條數據發生變化,只觸發一次
6. 觸發條件
當存在 WHEN 時, 只有滿足 WHEN 后面的條件 觸發動作執行
沒有 WHEN 條件存在時, 默認觸發動作執行。
7.觸發動作體
觸發動作體 既可以是一個匿名 PL/SQL 過程塊,也可以是對已創建存儲過程的調用,如果是行觸發器,在兩種情況下,用戶都可以在過程體中使用 NEW 和 OLD 引用 UPDATE/INSERT 事件之后的新值和 UPDATE/DELETE 事件之前的舊值,如果是語句級觸發器,則不能在觸發動作體中使用 NEW 或 OLD 進行引用。
如果觸發動作體執行失敗,激活觸發器的時間就會終止執行,觸發器的目標或觸發器可能影響的其他對象不發生任何變化。
例:定義一個BEFORE 行級觸發器,為教師表 Teacher 定義完整性規則“教授的工資不得低于4000 元,如果低于4000元 自動改為4000元”。
CREATE TRIGGER Insert_Ur_Update_Sal /* 在教室表 Teacher 上定義觸發器 */
BEFORE INSERT OR UPDATE ON Teacher /* 觸發事件是插入或更新操作 */
FOR EACH ROW /* 這是行級觸發器 */
AS BEGIN /* 定義觸發動作體,這是一個 PL/SQL 過程塊 */
IF (new.pJub='教授') AND (new.Sal < 4000) THEN /* 因為是行級觸發器,可在 */
new.Sal := 4000; /* 過程中使用插入或更新操作后的新值 */
END IF
END; /* 觸發動作體結束 */
例:定義 AFTER 行級觸發器,當教師表 Teacher 的工資發生變化后就自動在工資變化表 Sal_log 中增加一條相應記錄
CREATE TABLE Sal_log
(Eno NUMERIC(4) refereace teacher(eno)
Sal NUMERIC(7,2),
Username char(10),
Date TIMESTAMP
);
CREATE TRIGGER Insert_Sal /* 建立了一個觸發器 */
AFTER INSERT ON Teacher /* 觸發器事件是 INSERT */
FOR EACH ROW
AS BEGIN
INSERT INTO Sal_log VALUES(
new.Eno, new.Sal, CURRENT_USER, CURRENT_TIMESTAMP);
END;
CREATE TRIGGER Update_Sal /* 建立一個觸發器 */
AFTER UPDATE ON Teacher /* 觸發器事件是 UPDATE */
FOR EACH ROW
IF(new.Sal<>old.Sal) THEN INSERT INTO Sal_log VALUES(
new.Eno, new.Sal, CURRENT_USER, CURRENT_TIMESTAMP);
END IF;
END;
-
激活觸發器
觸發器執行,由觸發事件激活,由數據庫服務器自動執行。同一張表上多個觸發器激活時遵循如下的執行順序
- 執行該表上的 BEFORE 觸發器
- 激活觸發器的 SQL 語句
- 執行該表上的 AFTER 觸發器
-
刪除觸發器
語句如下:DROP TRIGGER <觸發器名> ON <表名>
觸發器必須是一個已經創建的觸發器,并且只能由具有相應權限的用戶刪除