- 【例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)