- 【例5.1】~【例5.13】ref:https://blog.csdn.net/qq_38975453/article/details/105253934
【例5.14】~【例5.17】瞭解一下即可。【例5.18】~【例5.20】瞭解一下即可。- 【例5.21】~【例5.23】ref:https://blog.csdn.net/qq_38975453/article/details/104729884
- 【例8.8】~【例8.9】ref:https://blog.csdn.net/qq_38975453/article/details/104729681
1. 在SQLserver上運行,觀察運行效果,並把代碼寫到作業中。
2. 寫出自己的理解/收穫/心得體會(部分比較複雜的例題,建議增加測試方法和測試數據,舉一反三)。
作業原地址:作業
目錄
【5.1 實體完整性】
5.1.1 定義實體完整性
對單屬性構成的碼有兩種說明方法,一種是定義爲列級約束條件,另一種是定義爲表級約束條件。
對多個屬性構成的碼只有一種說法,即定義爲表級約束條件。
【例5.1】將Student表中的Sno屬性定義爲碼。
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY, /*在列級定義主義*/
Sname CHAR(20) NOT NULL,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20)
);
或
CREATE TABLE Student
(Sno CHAR(9),
Sname CHAR(20) NOT NULL,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20),
PRIMARY KEY (Sno) /*在表級定義主碼*/
);
【例5.2】將SC表中的Sno、Cno屬性組定義爲碼。
CREATE TABLE SC
(Sno CHAR(9) NOT NULL,
Cno CHAR(4) NOT NULL,
Grade SMALLINT,
PRIMARY KEY (Sno,Cno) /*只能在表級定義主碼*/
);
5.12 實體完整性檢查和違約處理
用PRIMARY KEY 短語定義了關係的主碼後,每當用戶程序對基本表插入一條記錄或對主碼列進行更新操作時,實體完整性規則自動進行檢查。包括:
(1)檢查主碼值是否唯一,如果不唯一則拒絕插入或修改。
(2)檢查主碼的各個屬性是否爲空,只要有一個爲空就拒絕插入或修改。
【5.2 參照完整性】
5.2.1 定義參照完整性
關係模型的參照完整性在CREATE TABLE 中用 FOREIGN KEY 短語定義哪些列爲外碼,用REFERENCES 短語指明這些外碼參照哪些表的主碼。
【例5.3】定義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) /*在表級定義參照完整性*/
);
5.2.2 參照完整性檢查和違約處理
被參照表(例如Student) | 參照表(例如SC) | 違約處理 |
---|---|---|
可能破壞參照完整性 | 插入元組 | 拒絕 |
可能破壞參照完整性 | 修改外碼值 | 拒絕 |
刪除元組 | 可能破壞參照完整性 | 拒絕/級連刪除/設置爲空值 |
修改主碼值 | 可能破壞參照完整性 | 拒絕/級連刪除/設置爲空值 |
當不一致發生時,系統處理方式:
(1)拒絕(NO ACTION)執行
(2)級聯(CASCADE)操作
(3)設置爲空值
【例5.4】顯式說明參照完整性的違約處理示例。
CREATE TABLE SC
(Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY(Sno,Cno), /*在表級定義實體完整性,Sno、Cno都不能取空值*/
FOREIGN KEY(Sno) REFERENCES Student(Sno) /*在表級定義參照完整性*/
ON DELETE CASCADE
/*當刪除Student表中的元組時,級聯刪除SC表中相應的元組*/
ON UPDATE CASCADE,
/*當更新Student表中的sno時,級聯更新SC表中相應的元組*/
FOREIGN KEY (Cno) REFERENCES Course(Cno) /*在表級定義參照完整性*/
ON DELETE NO ACTION
/*當刪除Course 表中的元組造成了與SC表不一致時,拒絕刪除*/
ON UPDATE CASCADE
/*當更新course表中的cno時,級聯更新SC表中相應的元組*/
);
【5.3 用戶定義的完整性】
5.3.1 屬性上的約束條件
1.屬性上約束條件的定義
在CREATE TABLE 中定義屬性的同時,可以根據應用要求定義屬性上的約束條件,即屬性值限制,包括:
- 列值非空(NOT NULL)
- 列值唯一(UNIQUE)
- 檢查列值是否滿足一個條件表達式(CHECK)
(1)不允許取空值
【例5.5】在定義SC表時,說明Sno、Cno、Grade屬性不允許取空值。
CREATE TABLE SC
(Sno CHAR(9) NOT NULL, /*Sno屬性不允許取空值*/
Cno CHAR(4) NOT NULL, /*Cno屬性不允許取空值*/
Grade SMALLINT NOT NULL, /*Grade屬性不允許取空值*/
PRIMARY KEY(Sno, Cno), /*在表級定義實體完整性,隱含了Sno、Cno不允許
取空值,在列表不允許取空值的定義可不寫*/
...
);
(2)列值唯一
【例5.6】建立部門表DEPT,要求部門名稱Dname列取值唯一,部門編號Deptno列爲主碼。
CREATE TABLE DEPT
(Deptno NUMERIC(2),
Dname CHAR(9) UNIQUE NOT NULL, /*要求Dname列值唯一, 並且不能取空值*/
Location CHAR(10),
PRIMARY KEY(Deptno)
);
(3)用CHECK短語指定列值應該滿足的條件
【例5.7】Student表的Ssex只允許取“男”或“女”。
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY, /*在列表定義主碼*/
Sname CHAR(8) NOT NULL, /*Sname屬性不允許取空值*/
Ssex CHAR(2) CHECK(Ssex IN ('男','女')),
/*性別屬性Ssex只允許取'男'或'女'*/
Sage SMALLINT,
Sdept CHAR(20)
);
【例5.8】SC表的Grade的值應該在0和100之間。
CREATE TABLE SC
(Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT CHECK(Grade>=0 AND Grade<=100), /*Grade取值範圍是0到100*/
PRIMARY KEY(Sno,Cno),
FOREIGN KEY(Sno) REFERENCES Student(Sno),
FOREIGN KEY(Cno) REFERENCES Course(Cno)
);
2.屬性上約束條件的檢查和違約處理
當往表中插入元組或修改屬性的值時,關係數據庫管理系統將檢查屬性上的約束條件是否被滿足,如果不滿足則操作被拒絕執行。
5.3.2 元組上的約束條件
1.元組上約束條件的定義
【例5.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兩個屬性值之間的約束條件*/
);
2.元組上約束條件的檢查和違約處理
當往表中插入元組或修改屬性的值時,關係數據庫管理系統將檢查元組上的約束條件是否被滿足,如果不滿足則操作被拒絕執行。
5.4 完整性約束命名子句
1.完整性約束命名子句
CONSTRAINT <完整性約束條件名><完整性約束條件>
<完整性約束條件>包括NOT NULL、UNIQUE、PRIMARY KEY短語、FOREIGN KEY短語、CHECK短語等。
【例5.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)
);
【例5.11】建立教師表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 TEACHERFKey FOREIGN KEY(Deptno) REFERENCES DEPT(Deptno),
CONSTRAINT C1 CHECK (Sal+Deduct>=3000)
);
2.修改表中的完整性限制
可以使用ALER TBALE 語句修改表中的完整性限制。
【例5.12】去掉例5.10 Student表中對性別的限制。
ALTER TABLE Student
DROP CONSTRAINT C4;
【例5.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.7 觸發器】
觸發器,是用戶定義在關係表上的一類由事件驅動的特殊過程。
5.7.1 定義觸發器
觸發器又叫做 事件-條件-動作 規則。
當特定的特殊事件發生時,對規則的條件進行檢查,如果條件成立則執行規則中的動作,否則不執行改動作。
GREATE TRIGGER 命令建立觸發器。
CREATE TRIGGER <觸發器名>
{BEFORE | AFTER} <觸發事件> ON <表名>
REFERENCING NEW|OLD ROW AS<變量>
FOR EACH {ROW | STATEMENT}
[WHEN <觸發條件>]<觸發動作體>
【例5.21】當對錶SC的Grade屬性進行修改時,若分數增加了10%則將此次操作記錄到下面表中: SC_U(Sno,Cno,Oldgrade,Newgrade) 其中Oldgrade是修改前的分數,Newgrade是修改後的分數。
CREATE TRIGGER SC_T /*SC_T是觸發器的名字*/
AFTER UPDATE OF Grade ON SC /*UPDATE OF Grade ON SC 是觸發條件*/
/*AFTER 是出發的時機,表示當對SC的Grade屬性修改完後再出發下面的規則*/
REFERENCING
OLDROW AS OldTuple,
NEWROW AS NewTuple
FOR EACH ROW /*行級觸發器,即每執行每一次Grade的更新,下面的規則就執行一次*/
WHEN (NewTuple.Grade>=1.1*OldTuple.Grade) /*觸發條件,只有條件爲真時才執行*/
INSERT INTO SC_U(Sno,Cno,OldGrade,NewGrade) /*下面的INSERT操作*/
VALUES(OldTuple.Sno,OldTuple.Cno,OldTuple.Grade,NewTuple.Grade)
【例5.22】將每次對錶Student的插入操作所增加的學生個數記錄到表StudentInsertLog中。
CREATE TRIGGER Student_Count
AFTER INSERT ON Student /*指明觸發器激活的時間是在執行INSERT後*/
REFERENCING
NEW TABLE AS DELTA
FOR EACH STATEMENT
/*語句級觸發器,即執行完INSERT語句後下面的觸發動作體才執行一次*/
INSERT INTO StudentInsertLog (Numbers)
SELECT COUNT(*) FROM DELTA
【例5.23】定義一個BEFORE行級觸發器,爲教師表Teacher定義完整性規則“教授的工資不得低於4000元,如果低於4000元,自動改爲4000元”。
CREATE TRIGGER Insert_Or_Update_Sal /*對教師表插入或更新時激活觸發器*/
BEFORE INSERT OR UPDATE ON Teacher /*BEFORE觸發事件*/
FOR EACH ROW /*這是行級觸發器*/
BEGIN /*定義觸發動作體,是PL/SQL過程塊*/
IF(new.Job='教授') AND (new.Sal<4000)
/*因爲是行級觸發器,可在過程體重*/
THEN new.Sal :=4000; /*使用插入或更新操作後的新值*/
END IF;
END; /*觸發動作體結束*/
存儲過程
【例8.8】利用存儲過程來實現下面的應用:從賬戶1轉指定數額的款項到賬戶2中
CREATE OR REPLACE PROCEDURE TRANSFER(inAccount INT,outAccount INT,amount FLOAT)
/*定義存儲過程TRANSFER,參數爲轉入賬戶、轉出賬戶、轉賬額度*/
AS DECLARE /*定義變量*/
totalDepositOut Float;
totalDepositIn Float;
inAccountnum INT;
BEGIN /*檢查轉出賬戶的餘額*/
SELECT Total INTO totalDepositOut FROM Accout
WHERE accountnum=outAccount;
IF totalDepositOut IS NULL THEN /*如果轉出賬戶不存在或賬戶中沒有存款*/
ROLLBACK; /*回滾事務*/
RETURN
END IF;
IF totalDepositOut< amount THEN /*如果賬戶存款不足*/
ROLLBACK; /*回滾事務*/
RETURN
END IF
SELECT Accountnum INTO inAccountnum FROM Account
WHERE accountnum=inAccount;
IF inAccount IS NULL THEN /*如果轉入賬戶不存在*/
ROLLBACK; /*回滾事務*/
RETURN;
END IF;
UPDATE Account SET total=total-amount WHERE accountnum=outAccount;
/*修改轉出賬戶餘額,減去轉出額 */
UPDATE Account SET total=total + amount
WHERE accountnum=inAccount; /* 修改轉入賬戶餘額,增加轉入額 */
COMMIT; /*提交轉賬事務 */
END;
【例8.9】從賬戶01003815868轉10000元到01003813828賬戶中。
CALL PROCEDURE TRANSFER(01003813828,01003815868,10000`);
總結
這章稍微有點難了,感覺有點亂。還好老師已經發了博客,有參考也能多研究些。
完成時間:1h43min
以上
————(2020.4.5)