《数据库系统概论》 第5章——数据库完整性

虽然写这个博客主要目的是为了给我自己做一个思路记忆录,但是如果你恰好点了进来,那么先对你说一声欢迎。我并不是什么大触,只是一个菜菜的学生,如果您发现了什么错误或者您对于某些地方有更好的意见,非常欢迎您的斧正!

目录

5.1实体完整性

5.1.1定义实体的完整性

5.1.2实体完整性检查和违约处理

5.2参照完整性

5.2.1定义参照完整性

5.2.2参照完整性检查和违约处理

5.3用户自定义的完整性

5.3.1属性上的约束条件

5.3.2元组上的约束条件

 

5.4完整性约束命名子句

5.6断言

5.7触发器

 

5.7.1定义触发器

5.7.2激活触发器

5.7.3删除触发器


5.1实体完整性

5.1.1定义实体的完整性

实体完整性规则:若属性(一个或者一组)A是基本关系的主属性,则A不能取空值。

(主属性不能为空)

关系模型的实体完整性CREATE TABLE 中 用 PRIMARY KEY 定义

❸单属性构成的码有两种说明方法:

♦定义为列级约束条件

♦定义为表级约束条件

❹对多个属性构成的码只有一种说明方法:定义为表级约束条件

例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.1.2实体完整性检查和违约处理

●插入或对主码列进行更新操作时,DBMS按照实体完整性规则自动进行检查。包括:

1.检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改;(非空

2.检查主码值是否唯一,如果不唯一则拒绝插入或修改(唯一

●为了检查是否唯一,需要进行全表扫描。这听起来就很费时间,你插入的数据越多,你每次再插入的时候就需要全部遍历,这简直太糟糕了!我们就可以选择使用B+树索引。

B+树,具体可以参考我的博客:《算法导论》第十八章——B树

 

5.2参照完整性

▶关系模型的参照完整性规则:属性F 是关系R的外码,和关系S的主码相对应,则F 的取值等于S中某个主码的值,或者取空

 

5.2.1定义参照完整性

▶在CREATE  TABLE 中用 FOREIGN KEY 短语定义哪些列为外码;

▶用REFERENCES短语指明这些外码参照哪些表的主码。

 

例5.3:关系SC中一个元组表示一个学生选修的某门课程的成绩,(Sno,Cno)是主码。Sno,Cno分别参照引用Student表的主码和Course表的主码。定义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参照完整性检查和违约处理

拒绝(NO ACTION)执行

        ▶默认策略

级联(CASCADE)操作

        ▶如从Student表中删除Sno的值为201215121,则从sc表中级连删除 SC.Sno=201215121的所有元组

设置为空值(SET-NULL)

        ▶对于参照完整性,除了应该定义外码,还应定义外码列是否允许空值

        ▶如:学生 (学号, 姓名, 年龄,专业号  )    专业(专业号, 专业名)

                如果专业表中某个元组被删除,则可以把学生中的外码设置为空值

例5.4:显示说明参照完整性的违约处理示例。

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 CASCADE,/*当删除Student表中的元组时,级联删除SC表中相应的元组*/
	FOREIGN KEY (CNO) REFERENCES course (CNO) 
        ON UPDATE CASCADE /*当更新course表中的cno时,级联更新SC表中相应的元组*/
);

5.3用户自定义的完整性

▶用户定义的完整性就是针对某一具体应用的数据必须满足的语义要求

▶RDBMS(关系数据库管理系统)提供了定义和检验这类完整性的机制,使用了和实体完整性、参照完整性相同的方法来处理他们,而不必由应用程序承担。

5.3.1属性上的约束条件

❶属性上约束条件的定义

        ▶列值非空(NOT NULL)

        ▶列值唯一(UNIQUE)

        ▶检查列值是否满足一个布尔表达式(CHECK)

①不允许取空值

例5.5:在定义SC表时,说明Sno、Cno、Grade属性不允许取空值。(NOT NULL

CREATE TABLE sc (
	SNO CHAR (9) NOT NULL,/*Sno属性不允许取空值*/
	CNO CHAR (4) NOT NULL,/*Cno属性不允许取空值*/
	GRADE SMALLINT,/*Grade属性不允许取空值*/
	PRIMARY KEY (SNO, CNO),/ * 如果在表级定义实体完整性,隐含了Sno,Cno不
                                   允许取空值,则在列级不允许取空值的定义就不必写了 * /
  ...
);

 

②列值唯一

例5.6:建立部门表DEPT,要求部门名称Dname列取值唯一,部门编号Deptno列为主码(UNIQUE

CREATE TABLE DEPT (
	Deptno NUMERIC (2),
	Dname CHAR (9) UNIQUE NOT NULL,/*要求Dname列值唯一*/
	Location CHAR (10),
	PRIMARY KEY (Deptno)
);

例5.7:Student表的Ssex只允许取“男”或“女”(CHECK(Ssex IN(,))

CREATE TABLE student (
	SNO CHAR (9) PRIMARY KEY,
	SNAME CHAR (8) NOT NULL,
	SSEX CHAR (2) CHECK (SSEX IN('男', '女')),/*性别属性Ssex只允许取'男'或'女' */
	SAGE SMALLINT,
	SDEPT CHAR (20)
);

例5.8:SC表的Grade值应该在0~100之间(CHECK(Grade>=0 AND Grade<=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)
);

属性上约束条件的检查和违约处理

▶当往表中插入元组或修改属性值时,关系数据库管理系统(RDBMS)将检查属性上的约束条件是否被满足,如果不满足则操作被拒绝执行

5.3.2元组上的约束条件

元组上约束条件的定义

▶在CREATE TABLE时可以用CHECK短语定义元组上的约束条件,即元组级的限制

▶同属性值限制相比,元组级的限制可以设置不同属性之间的取值的相互约束条件

例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 (             /*定义了元组中Sname和 Ssex两个属性值之间的约束条件*/
		SSEX = '女'
		OR SNAME NOT LIKE 'MS.%'
	)
);

▶性别是女性的元组都能通过该项检查,因为Ssex=‘女’成立;

▶当性别是男性时,要通过检查则名字一定不能以Ms.打头

 

元组上约束条件的检查和违约处理

▶插入元组或修改属性的值时,RDBMS检查元组上的约束条件是否被满足

▶如果不满足则操作被拒绝执行

 

5.4完整性约束命名子句

▶在Creat table语句中提供了完整性约束命名子句CONSTRAINT,用来对完整性约束条件命名,从而可以灵活地增加、删除一个完整性约束条件。

 

完整性约束命名子句

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)
);

▶在Student表上建立了5个约束条件,包括主码约束(命名为StudentKey)以及C1C2C3C4四个列级约束。

例5.11:建立教师表,要求每个教师的工资不低于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)
);

❷修改表中的完整性限制

▶使用ALTER TABLE语句修改表中的完整性限制

 

例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.6断言

创建断言的语句格式

    CREATE ASSERTION  <断言名> <CHECK 子句>

▶每个断言都被赋予一个名字,<CHENCK子句>。

▶可以定义涉及多个表或者聚集操作的比较复杂的完整性约束条件;

▶断言创建以后,任何对断言中所涉及的操作都会触发关系数据库管理系统对断言的检查,使断言不为真值的操作都会被拒绝。

▶在SQL中可以使用数据定义语言中的CREATE  ASSERTION语句,通过声明断言来指定更具一般的约束条件

例5.18:限制数据库课程最多60名学生选修

CREATE ASSERTION ASSE_SC_DB_NUM
   CHECK(60>=(SELECT COUNT(*)
              FROM course,sc
              WHERE sc.CNO=course.CNO AND course.CNAME='数据库')
);

例5.19:限制每一门课程最多60名学生选修

CREATE ASSERTION ASSE_SC_CNUM1
   CHECK(60>=(SELECT COUNT(*)/*此断言的谓词,涉及聚集操作count*/
              FROM sc        /*和分组函数group by的SQL语句*/
              GROUP BY CNO)
);

例5.20:限制每个学期每一门课程最多60名学生选修

ALTER TABLE sc ADD TERM DATE;/*修改SC表,增加TERM属性,它的类型是DATE*/
CREATE ASSERTION ASSE_SC_CNUM2
   CHECK(60>=(SELECT COUNT(*)
              FROM sc        
              GROUP BY CNO,TERM)
);

5.7触发器

触发器(Trigger)是用户定义在关系表上的一类由事件驱动的特殊过程,一旦定义,用户对表的增、删、改操作均由服务器自动激活相应的触发器,在DBMS(关系数据管理系统)核心层进行完整性控制。

▶由服务器自动激活

▶类似于约束,但比约束更加灵活,可以进行更为复杂的检查和操作,具有更精细和更强大的数据控制能力

 

5.7.1定义触发器

触发器: 又叫“事件 - 条件 - 动作(event-condition-action)”规则,当特定的系统事件发生时,对规则的条件进行检查,触发器类似于约束,但是比约束更灵活。如果条件成立则执行规则中的动作,否则不执行该动作。

CREATE TRIGGER 语法格式

    CREATE TRIGGER <触发器名>  

            { BEFORE | AFTER }  <触发事件> ON <表名>

      FOR EACH  { ROW | STATEMENT }

            [ WHEN <触发条件>]  <触发动作体>

▶定义触发器的语法说明:

1. 创建者:表的拥有者,一个表上创建触发器的数目由具体的DBMS确定;

2. 表名:触发器的目标表,不能定义在视图上;

3. 触发事件:INSERT、DELETE、UPDATE,也可以是几个事件的组合;

         如INSERT OR UPDATE, 还可以是UPDATE OF <触发列,… >

4. 触发器类型

   行级触发器(FOR EACH ROW);

   语句级触发器(FOR EACH STATEMENT)

5. 触发条件

触发条件为真

省略WHEN触发条件: 触发动作在触发器激活后立即执行

6. 触发动作体

触发动作体可以是一个匿名SQL过程块,也可以是对已创建存储过程的调用

如果是行级触发器,用户可以在过程体中使用NEW和OLD引用UPDATE/ INSERT前后的旧值和新值;如果是语句级触发器,则不能用NEW和OLD引用

例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是触发的时机*/
REFERENCING
   OLDROW AS OLDTUPLE,
   NEWROW AS NEWTUPLE
FOR RACH ROW/*行级触发器,即每执行一次grade的更新,下面的规则就执行一次*/
WHERE(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的插入操作所增加的学生个数记录到表studnet-InsertLog中

CREATE TRIGGER Student_Count
AFTER INSERT ON student
REFERENCING
   NEW TABLE AS DELTA
   FOR EACH STATEMENT/*语句级触发器,即执行完INSET语句后下面的触发动作才执行一次*/
      INSERT INTO StudentInsertLog(NUMBERS)
      SELECT COUNT(*) FROM DELTA

例5.23:定义一个BEFORE行级触发器,为教师表Teacher定义完整性规则“教授的工资不得低于8000元,如果低于8000元,自动改为8000元”

CREATE TRIGGER Insert_Or_Update_Sal/*对教师表进行插入或删除的时候才激发*/
BEFORE INSERT OR UPDATE ON TEACHER/*BEFORE触发事件*/
REFERENCING NEW ROW AS  NEWTUPLE
FOR EACH ROW/*这是行级触发器*/
BEGIN   /*定义触发动作提*/
   IF(NEWTUPLE.JOB='教授')AND(NEWTUPLE.SAL<4000)
       THEN NEWTUPLE.SAL:=4000;
   END IF;
END;

 

5.7.2激活触发器

▶触发器的执行,是由触发事件激活的,并由数据库服务器自动执行一个数据表上可能定义了多个触发器

▶同一个表上的多个触发器激活时遵循如下的执行顺序:

 1)执行该表上的BEFORE触发器;

 2)激活触发器的SQL语句;

 3)执行该表上的AFTER触发器,对于同一表上有多个触发器,遵循“谁先创建谁先执行” 的原则.

 

5.7.3删除触发器

▶删除触发器的SQL语法:

       DROP TRIGGER <触发器名> ON <表名>;

▶触发器必须是一个已经创建的触发器,并且只能由具有相应权限的用户删除

   【例】  删除教师表Teacher上的触发器 Insert_Sal

            DROP TRIGGER Insert_Sal ON Teacher;

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值