数据库
首页 > 数据库> > 数据库第五讲 完整性

数据库第五讲 完整性

作者:互联网

第五讲 完整性

完整性概述

数据库的完整性是指数据库中数据的正确性 、一致性和相容性

约束的分类
就被约束的数据对象而言,完整性约束又可以分为如下表所示的四种类型

约束类型含义
类型/域约束说明给定类型的合法取值用户自定义的完整性
属性约束说明属性的合法取值用户自定义的完整性
关系约束说明关系的合法取值实体完整性/用户自定义的完整性
数据库约束说明数据库的合法取值,通常涉及多个关系参照完整性/用户自定义的完整性

从约束的状态的角度,约束还可以分静态约束和动态约束

DBMS对约束的支持

//1.提供说明和定义完整性约束的方法
	CTEATE TABLE Teachers
	(Tno	CHAR(7)PRIMARY KEY,
	Tname	CHAR(10),
	Sex		CHAR(2)CHECK(Sex='男'OR Sex = '女'),
	Birthday	DATE.
	Title	CHAR(6),
	Dno		CHAR(4),
	FOREIGN KEY (Dno) REFERENCES Departments(Dno));
//这条create语句定义了Teachers表 PRIMARY KEY(主码约束)、CHECK、FOREIGN KEY(外码约束)、REFERENCES 都是约束的定义

//2.提供完整性检查机制
//约束的定义都存放在数据字典里,每当用户更新数据时,DBMS都会进行完整性检查
//3.违约处理
//当更新违反了完整性约束时,DBMS会采取相应的措施,保证数据的完整性

实体完整性

实体完整性约束的定义

//创建选课表SC用如下语句
CREATE TABLE Sc
(Sno	CHAR(9),
Cno		CHAR(5),
Grade	SMALLINT CHECK(Grade>=0 ANDGrade<=100),
PRIMARY KEY (Sno,Cno),
FOREIGN KEY (Sno)REFERENCES Students(Sno),
FOREIGN KEY(Cno)REFERENCES Courses (Cno));

实体完整性规则

违反实体完整性规则的操作

//插入新元组时可以破坏实体完整性规则
INSERT INTO Students
VALUES('201816010','司马义','男',1999-01-28,'2018','计算数学','MATH')
//学号重复
//修改元组的主码时可以破坏实体完整性规则

违约处理
DBMS应该自动检查是否导致违反实体完整性约束,并拒绝导致破坏实体完整性约束的任何插入或修改

参照完整性

参照完整性约束的定义

//创建选课表SC用如下语句
CREATE TABLE Sc
(Sno	CHAR(9),
Cno		CHAR(5),
Grade	SMALLINT CHECK(Grade>=0 ANDGrade<=100),
PRIMARY KEY (Sno,Cno),
FOREIGN KEY (Sno)REFERENCES Students(Sno),
FOREIGN KEY(Cno)REFERENCES Courses (Cno));

外码与ER模型
参照完整性是对外码取值的约束,外码的来源有一下几种情况

下列关系模式中存在的外码
Departments(Dno , Dname, Dheadno)
Teachers(Tno , Tname,Sex, Birthday, Title, Dno)
Students(Sno , Sname,Sex, Birthday, Enrollyear,Speciality, Dno)
Courses(Cno ,Cname, Period, Credit)
Teaches (Tno,Cno )
sC(Sno,Cno ,Grade)
Evalues (Sno,Tno,Cno , Escore)

家属(职工号,家属姓名,性别,出生年月,与职工关系)

参照完整性规则
参照关系R的任何元组在其外码FKr上的值或者等于被参照关系S的某个元组在主码Ks上的值,或者为空值

违反参照完整性的更新

//例子
INSERT INTO SC(Sno,Cno)
VALUES('201816010','MA302')
//若Students中没有201816010这个学生,违反参照

DELETE FROM Students
WHERE Sno='201824010';
//从Students中删除201816010这个学生后,SC表中的这个学生的选课记录就没有可参照的对象,因此违反


UPDATE Students
SET Dno = 'CS'
WHERE Sno = '201824010'
//如果Department表中没有CS这个院系,则违反

违约处理

违约定义
定义外码时可以通过参照触发动作定义违约时出发的动作
FOREIGN KEY (A1,...,Ak)REFERENCES<外表名>(<外表主码>)

//例子:如果我们希望在修改Students元组的主码时,同时修改SC表中相应元组的外码,
//删除Students的元组时,同时删除相应的SC元组。
//而修改Courses的元组时,同时修改相应的SC元组的外码,但不允许删除Courses的元组,破坏参照完整性

CREATE TABLE SC
(Sno CHAR(9),
Cno CHAR(5),
Grade SMALLINT CHECK (Grade>=O AND Grade<=100),
PRIMARY KEY (Sno,Cno),
FOREIGN KEY (Sno)REFERENCES Students (Sno)
	ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (Cno)REFERENCES Courses (Cno)
	ON UPDATE CASCADE );

用户自定义的完整性

用户自定义的完整性约束:用户定义的完整性即是针对某个特定关系数据库的约束条件,它反映某一具体应用所涉及的数据必须满足的语义要求,用户定义的完整性可以是∶属性级、关系级、数据库级

属性级约束
属性级的用户自定义约束指的是定义在列级上的CHECK约束、NULL约束、UNIQUE约束

CREATE TABLE Students
(Sno	CHAR(9) PRIMARY KEY,
Sname	CHAR(10)NOT NULL,
Sex	CHAR(2)CHECK(Sex='男'OR Sex='女'),
Birthday	DATE,
Enrollyear CHAR(4),
Speciality	CHAR(20),
Dno	CHAR (4),
FOREIGN KEY (Dno)REFERENCES Department (Dno));

关系级约束
关系级约束说明关系的合法取值,常常涉及同一关系的多个属性和/或多个元组

//EmpSalary (职工工资)表具有如下模式∶
EmpSalary(Eno,Ename, Dno, BaseSalary, Subsidy, Bonus,Tax, Insurance,PayLoan)
CREATE TABLE EmpSalary
(Eno	CHAR (7)PRIMARY KEY,
Ename	CHAR(8)NOT NULL,
Dno		CHAR(4),
BaseSalary	NUMERIC (7,2),
Subsidy		NUMERIC (7,2),
Bonus	NUMERIC (7,2),
Tax		NUMERIC (7,2),
Insurance NUMERIC (7,2),
PayLoan NUMERIC (7,2)DEFAULT 0.00,
CHECK(((BaseSalary+Subsidy+Bonus)-(Tax+Insurance+PayLoan))>=0.5* BaseSalary)
FOREIGN KEY(Dno)REFERENCES Departments (Dno));

断言与数据库级约束

CREATE ASSERTION<断言名>
CHECK(<条件>)[<约束性质>]

例子:设数据库包含如下关系模式:Employees (Eno, Ename, Salary,Dno),Departments (Dno, Dptname, Mrgno)
约束“任何部门经理的工资不超过其所在部门平均工资的10倍”涉及上述两个关系,可以为它创建一个断言,该约束等价于“不存在一个部门经理,其工资高于他所在部门平均工资的10倍。”可以用SQL创建一个断言SalaryConstraint来表达这一约束:

CREATE ASSERTION SalaryConstraint CHECK
(NOT EXISTS
(SELECT*
FROM Departments D, Employees E
WHERE D.Mrgno=E.Eno AND
Salary>10*(SELECT AVG (Salary)
FROM Employees
WHERE Dno=D.Dno)));

在这里插入图片描述
例子:

触发器

问题引入:
虽然DBMS提供了多种完整性约束定义和检查机制。然而,除了违反参照完整性约束的删除和修改进行级联删除和修改外,违反其他约束的更新都被简单地拒绝
两个例子∶

触发器(trigger) 是特殊类型的存储过程,当某个事件发生时它自动执行
要设置触发器机制,必须满足两个要求:

SQL中的触发器
在SQL-92标准中没有触发器,但是支持SQL的DBMS广泛支持触发器。然而,不同系统的触发器并不兼容
下面介绍基于sQL-99中的触发器,IBM DB2和Oracle中的触发器与此类似
创建触发器语句的一般格式如下:

CREATE TRIGGER<触发器名>触发时间><触发事件>ON<表名>
[REFERENCING<旧/新值别名>,...,<旧/新值别名>]
[FOR EACH {ROW | STATEMENT}]
[WHEN (<触发条件>)]<被触发的SQL语句>
/*
<触发时间>可以是BEFORE:事件前,AFTER:事件后

<触发事件>可以是T上的INSERT、DELETE、UPDATE或UPDATE OF<触发列>,...<触发列>

REFERENCING子句创建一些过渡变量用来存放表T和表T的行更新前的l旧值和更新后的新值。

<旧/新值别名>可以是如下形式之一
	OLD/NEW[RoW][AS]<变量>︰创建行过渡变量<变量>存放表T的行更新前/后的值
	OLD/NEW TABLE [AS]<变量>∶创建表过渡变量<变量>存放表T更新前/后的值
	
FOR EACH ROW定义行级触发器,而FOR EACH STATEMENT定义语句级触发器缺省时为语句级触发器

WHEN子句说明触发条件,缺省时无条件触发。<触发条件>是一个任意布尔表达式

<被触发的SQL语句>是触发动作体,具有如下形式:
	BEGIN ATOMIC
		<可执行的SQL语句>;
	END

*/

例子:
设银行数据库包含如下关系模式︰

某元组t的Balance修改后的值小于零时,系统做如下三件事:

CREATE TRIGGER OverdraftTrigger 
AFTER UPDATE OF Balance ON Account
REFERENCING NEW ROW AS t
FOR EACH ROW
WHEN (t.Balance < 0)
BEGIN ATOMIC
	INSERT INTO Loan
	VALUES (t.AccountNumber, t.BranchName, -t.Balance);
	INSERT NTO Borrower
	(SELECT CustomerName, AccountNumber
	FROM Depositor
	WHERE t.AccountNumber = Depositor.AccountNumber);
	UPDATE Account SET Balance= 0
	WHERE Account.AccountNumber = t.AccountNumber
END

删除触发器
当触发器没用时可以删除它,语法如下:DROP TRIGGER <触发器名>

标签:触发器,数据库,元组,CHAR,第五,完整性,约束,Dno
来源: https://blog.csdn.net/usinganame/article/details/116667214