数据库实验六 数据库的完整性

实验六 数据库的完整性

一、实验目的

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仅支持行级触发器

你可能感兴趣的:(课程学习记录)