数据库的完整性是指数据的正确性和相容性。
数据的正确性是指数据是符合现实世界语义、反映当前实际情况的;数据的相容性是指数据库同一对象在不同关系表中的数据是符合逻辑的。
数据的完整性和安全性是两个既有联系又不尽相同的概念。数据的完整性是为了防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据。数据安全性是保护数据库防止恶意破坏和非法存取。
关系数据库管理系统使得完整性控制成为其核心支持的功能,从而能够为所有用户和应用提供一致的数据库完整性。
实体完整性
关系模型的实体完整性在CREATE TABLE 中使用 PRIMARY KEY来定义。对单属性构成的码有两种说明方法,一种是列级约束条件,一种是表级约束条件,对多个属性构成的码则只有表级约束条件这一种说明方法。
用PRIMARY KEY短语定义好关系的主码后,每当用户程序对基本表插入一条记录或对主码列进行更新操作时,关系数据库管理系统将按照实体完整性规则进行自动检查:
检查主码值是否唯一,若不唯一则拒绝插入或修改
检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改
检查记录中主码值是否唯一的一种方法是进行全表扫描,依次判断表中的每一条记录的主码值与将要插入记录值(或者修改的新主码值)是否相同。
由于全表扫描十分耗时,故关系数据库管理系统一般都会在主码上自动建立一个索引,例如,数据结构中的B+树索引,从根节点出发依次向下寻找,大大缩减了扫描的时间。
参照完整性
关系模型的参照完整性在CREATE TABLE 中用FOREIGN KEY短语定义哪些列为外码,用REFERENCES短语指明外码参照了哪些表的主码。
参照完整性将两个表中的相应元组联系起来了,因此,对被参照表和参照表进行增、删、改操作时都有可能会破坏参照完整性,必须进行检查以保证两个表的相容性。
当操作破坏了参照完整性时,系统可以采用以下策略进行处理:
拒绝执行,一般为默认策略
级联操作,删除或修改所有预期相关的元组
设置为空值,将那个参照表中的所有造成不一致的元组的对应属性设置为空值。
用户自定义完整性
用户定义的完整性就是针对某一具体应用的数据必须满足的语义要求。
在CREATE TABLE 中定义属性时,可以根据应用要求定义属性上的约束条件,即属性值限制,包括:
列值非空(NOT NULL)
列值唯一(UNIQUE)
检查列值是否满足一个条件表达式(CHECK短语)
当往表中插入元组或修改属性的值时,关系数据库系统将检查属性上的约束条件是否被满足,如果不满足则操作被拒绝执行。
与属性上约束条件类似,在CREATE TABLE 中可以使用CHECK短语定义元组上的约束条件,即元组级的限制,同属性值限制相比,元组级的限制可以设置不同属性之间的取值的相互约束条件。
当往表中插入元组或修改属性的值时,关系数据库系统将检查元组上的约束条件是否被满足,若不满足,则拒绝执行操作。
完整性约束子句
SQL还在CREATE TABLE语句中提供了完整性约束命名子句CONSTRAINT,用来对完整性约束条件命名,从而可以灵活地增加、删除一个完整性约束条件。
eg. 建立学生登记表Student,要求学号在90000~99999之间,姓名不能取空值,年龄小于30岁,性别只能是”男“或”女“。
CREATE TABLE Student
(Sno NUMERIC(6)
CONSTRAINT C1 CHECK(Sno BETWEEN 90000 TO 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)
);
eg. 去掉上例Student表中对性别的限制。
ALTER TABLE Student
DROP CONSTRAINT C4;
eg. 修改表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);
除此之外,SQL中还支持对域的声明和修改、删除等,通过修改域上的值,可以达到同时修改多个不同表上的完整性约束的效果。其相关的SQL语句和完整性约束子句基本一致,只不过TABLE换成了DOMAIN而已,这里就不做赘述了。
触发器
触发器是用户定义在关系表上的一类由事件驱动的特殊过程。
SQL中建立触发器的语句如下:
CERATE TRIGGER <触发器名称> /*每当触发事件发生时,触发器被激活*/
{BEFORE|AFTER} <触发事件> ON <表名> /*指明是事前触发还是事后触发*/
REFERENCING NEW|OLD ROW AS <变量> /*REFERENCING指出引用的变量*/
FOR EACH {ROW|STATEMENT} /*定义触发器的类型,指明动作体执行的频率*/
[WHEN<触发条件><触发动作体>] /*仅当触发条件为真时,才执行动作体*/
注意:只有表的拥有者才可以在表上创建触发器。
eg. 定义一个BEFORE行级触发器,为教师表Teacher定义完整性规则”教师的工资不得低于4000元,如果低于4000元,自动改为4000元“。
CREATE TRIGGER Insert_Or_Update_Sal
BEFORE INSERT OR UPDATE ON Teacher
REFFERENCING NEW row AS newtuple
FOR EACH ROW
BEGIN
IF (newtuple.Job = '教授') AND (newtuple.Sal < 4000)
THEN newtuple.Sal = 4000;
END IF;
END;
触发器的执行是由触发事件激活,并由数据库服务器自动执行的。一个数据表上可以定义多个触发器,如多个BEFORE触发器、多个AFTER触发器等,同一个表上的触发器的激活顺序一般遵循如下准则:
执行该表上的BEFORE 触发器
激活触发器上的SQL语句
执行该表上的AFTER触发器
对于同一个表上的多个BEFORE(AFTER)触发器,遵循”谁先创建谁先执行“的原则。
删除触发器的语句如下:
DROP TRIGGER <触发器名称> ON <表名>
只有具有相应权限的用户才能删除触发器。