1.掌握实体完整性的定义和维护方法。
2.掌握参照完整性的定义和维护方法。
3.掌握用户自定义完整性的定义和维护方法。
4.掌0握触发器的设计和使用方法
1.定义实体完整性、删除实体完整性。
2.定义参照完整性,定义参照完整性的违约处理,删除参照完整性。
3.定义用户自定义完整性,删除用户自定义完整性。
4.定义before和after触发器。
要求:能够写出两种方式定义实体完整性的SQL语句:创建表时定义实体完整性、创建表后定义实体完整性;能够写出两种方式定义参照完整性的SQL语句:创建表时定义参照完整性、创建表后定义参照完整性;针对具体应用,选择not null,unique,check等,定义属性上的约束条件;设计SQL语句验证完整性约束是否起作用;能够理解不同类型触发器的作用和执行原理;验证触发器的有效性。
(一)考虑下面的关系模式:
研究人员(人员编号,姓名、年龄、职称)
项目(项目编号,名称,负责人编号,类别)
参与(项目编号,人员编号,工作时间)
一个研究人员可以参与多个项目,一个项目有多个研究人员参加,工作时间给出某个研究人员参加某项目的月数。
创建三张表,并定义下面的完整性约束:
(1)定义三个关系中的主码、外码、参照完整性;
(2)项目名称必须互不相同;
(3)每个研究人员的年龄不能超过35岁;
(4)每个研究人员的职称只能是“讲师”、“副教授”或“教授”
(5)设计SQL语句在表中进行插入、删除、修改操作验证完整性约束是否起作用
按照要求(1)、(2)、(3)、(4)创建表:
#研究人员表
#方法一:CREATE TABLE staff
( sno CHAR(10) PRIMARY KEY,
sname CHAR(10),
age INT CHECK(age<=35),
jobTitle CHAR(10) CHECK(jobTitle IN('讲师','副教授','教授'))
);
#方法二:CREATE TABLE staff
(sno CHAR(10),
sname CHAR(10),
age INT CHECK(age<=35),
JobTitle CHAR(10) CHECK(jobTitle IN('讲师','副教授','教授')),
PRIMARY KEY(sno)
);
#项目表
#方法一:CREATE TABLE project
(pno CHAR(10) PRIMARY KEY,
pname CHAR(50) UNIQUE NOT NULL,
fno CHAR(10),
type CHAR(10)
);
#方法二:CREATE TABLE project
( pno CHAR(10),
pname CHAR(50) UNIQUE NOT NULL,
fno CHAR(10),
type CHAR(10),
PRIMARY KEY(pno)
);
#参与表
CREATE TABLE attend
(pno CHAR(10),
sno CHAR(10),
time CHAR(50),
FOREIGN KEY(sno) REFERENCES staff(sno),
FOREIGN KEY(pno) REFERENCES project(pno)
);
(5)验证完整性约束是否起作用
验证主键 验证结果:插入失败,约束成功
INSERT
INTO staff
VALUES('111111','lyh',26,'教授');
INSERT
INTO staff
VALUES('111111','李贻慧',27,'教授');
验证外键 验证结果:插入失败,约束成功
INSERT
INTO attend
VALUES('001','111111','半年');
验证项目名称必须不同 验证结果:插入失败,约束成功
INSERT
INTO project
VALUES('01','数据库设计','001','数据库1');
INSERT
INTO project
VALUES('02','数据库设计','002','数据库2');
#验证研究人员的年龄不能超过35岁
INSERT
INTO staff
VALUES('2018413449','李贻慧','38','教授');
#验证研究人员的职称只能是“讲师”、“副教授”或“教授”
INSERT
INTO staff
VALUES('2018413449','李贻慧','26','博士');
(二)考虑(一)中的关系模式,使用alter table add constraint声明如下完整性约束:
(1)负责人编号参照研究人员的“人员编号”属性,当对“研究人员”修改时,若违反约束则将负责人编号置为NULL,当对“研究人员”删除时,若违反约束则将项目中的相应元组删除。
ALTER TABLE project
ADD CONSTRAINT c11 FOREIGN KEY(fno) REFERENCES staff(sno) ON DELETE SET NULL ON UPDATE SET NULL;
ALTER TABLE project
ADD CONSTRAINT c12 FOREIGN KEY(fno) REFERENCES staff(sno) ON DELETE CASCADE ON UPDATE CASCADE ;
(2)工作时间在1到12之间
ALTER TABLE attend
ADD CONSTRAINT c2 CHECK(time>=1 AND time<=12);
(3)研究人员姓名不能为空
ALTER TABLE staff
ADD CONSTRAINT c3 CHECK(sname IS NOT NULL);
(4)设计SQL语句在表中进行插入、删除、修改操作验证完整性约束是否起作用
验证语句: 验证结果
INSERT
INTO attend
VALUES('01','111111','15');
#验证研究人员姓名不能为空
INSERT
INTO staff(sno,age,jobTitle)
VALUES('222222',19,'讲师');
(三)删除完整性约束
(1)删除“参与”的外键
ALTER TABLE attend
DROP FOREIGN KEY attend_ibfk_1;
ALTER TABLE attend
DROP FOREIGN KEY attend_ibfk_2;
(2)删除“项目”的主键
ALTER TABLE project
DROP PRIMARY KEY;
(3)删除研究人员年龄的约束
ALTER TABLE staff
DROP CHECK staff_chk_1;
(四)创建触发器
(1)在s_t数据库中创建表summary(sno,ncourses,avg),包含学生学号、选修课程数量、平均分,并将目前每个学生选修课程数量和平均分存入该表。
#创建表
CREATE TABLE summary
(sno char(9) PRIMARY KEY,
ncourses int,
avg double
);
#存入数据
方法一:(之前在实验三中建立过一个相同功能的视图v_student,所以存入数据时把视图中的数据拿到存入即可)
INSERT
INTO summary
SELECT *
FROM v_student;
方法二:
INSERT
INTO summary
SELECT Sno,count(*),AVG(Grade)
FROM sc
GROUP BY Sno;
(2)创建触发器update_summary1,当修改了学生课程成绩时,更新summary表中该学生的平均分。
Create trigger update_summary1
After update on sc
For each row
Begin
UPDATE summary
SET avg =
(Select avg(Grade)
from sc
where sno=new.sno) WHERE sno=new.sno;
End;
(3)创建触发器update_summary2,当添加了学生选课记录时,更新summary表中该学生的选课数量和平均分。如果是该学生第一次选课,那么在summary表中插入一条新纪录。
CREATE TRIGGER update_summary2
after insert on sc
For each row
Begin
Set @nums = (Select count(*) from sc where sno=new.sno);
if @nums=1 then
INSERT INTO summary
VALUES(sno,1,grade);
Else
UPDATE summary
SET ncourses=ncourses+1,avg=(
Select avg(Grade)
from sc
where sno=new.sno) WHERE sno=new.sno;
End if;
End;
(4)创建触发器check_age,当添加学生记录时,如果该学生年龄小于18或没有提供年龄,则将其年龄设置为18。
CREATE TRIGGER check_age
before insert on student
For each row
Begin
if new.sage<18 or new.sage is null then
set new.sage=18;
End if;
End;
(5)创建触发器check_course,当添加学生选课记录时,检查该学生是否选修了此课程new.cno的直接先修课,如果没有则拒绝添加选课记录。
signal SQLSTATE ‘TX000’ SET MESSAGE_TEXT = ‘can not insert ……’;
这里了没写出来,运行有问题,改了好久
CREATE TRIGGER check_course
before insert on sc
For each row
Begin
select count(*) as count
from sc
where cno in
( Select cpno
from course
where cno=new.cno)
if count=0
signal SQLSTATE ‘TX000’ SET MESSAGE_TEXT = ‘can not insert’;
End if;
End;
一开始在建立表时,没有指定数据类型位char的长度,在定义sql语句,插入数据验证时发现,报长度过长的错误,打开各表,点击设计表,在可视化界面发现类型位char的长度均为1,总结:char类型不指定长度默认为1。故需指定char类型的长度。
再删除外键约束时遇到了问题,网上查找资料找到了解决方法
https://jingyan.baidu.com/article/4ae03de32dfe9a3eff9e6bdc.html
用show create table attend 可查看attend表的外键id,如下图
使用ALTER TABLE attend DROP FOREIGN KEY 外键id;即可删除对应外键
在删除staff表的年龄约束时也遇到了类似问题,依旧用show create table 表名语句查找对应的check。
mysql仅支持行级触发器