实验四:数据库完整性
一、实验目的
1.理解数据完整性的概念及分类
2.掌握各种数据完整性的实现方法
3.掌握触发器的使用方法
二、实验平台
1.操作系统:Windows XP 或者 Windows 7
2.数据库管理系统:SQL Server 2008
三、实验内容和要求
使用 SQL 对数据进行完整性控制(3 类完整性、CHECK 短语、CONSTRAINT
子句、触发器)。用实验证实,当操作违反了完整性约束条件时,系统是如何处
理的。在实验 2 中已经建立了一个数据库 students,继续在此数据库上进行实验
所要求的各种操作。认真填写实验报告,记录所有的实验用例。
四、实验步骤
在本实验中,我们将对完整性进行讨论,包括 3 类完整性、CHECK 短语、
CONSTRAIN 子句、触发器。因为完整性约束绝大部分是在定义表结构时进行的,
因此可能需要多次定义表,如果表名发生重复的话,可以先将旧表删除后再建立。
1. 实体完整性
[例 1]定义表的主码。
关系模型的实体完整性在 CREATE TABLE 中用 PRIMARY KEY 定义。定
义主码的方法分为定义为列级约束条件和定义为表级约束条件两种。
[例 1-1]定义表 Student,并将其中的 Sno 属性定义为主码。
CHAR(7) PRIMARY KEY,
CREATE TABLE STUDENT(
SNO
SNAME CHAR(8) NOT NULL,
CHAR(2),
SSEX
SAGE
SMALLINT,
SDEPT CHAR(20));
或者:
CHAR(7),
CREATE TABLE STUDENT(
SNO
SNAME CHAR(8),
CHAR(2),
SSEX
SAGE
SMALLINT,
SDEPT CHAR(20),
PRIMARY KEY (SNO));
[例 1-2]定义表 SC,将其中的属性 Sno,Cno 定义为主码。
对于多个属性构成的码,只能够将其定义为表级约束条件,而无法用列级约
束条件来实现。
CREATE TABLE SC(
SNO CHAR(7) NOT NULL,
CNO CHAR(4) NOT NULL,
GRADE SMALLINT,
PRIMARY KEY (SNO,CNO));
2. 参照完整性
[例 2]定义表的外码。
主码 Cno。
CREATE TABLE SC(
关系模型的参照完整性是在 CREATE TABLE 中用 FOREIGN KEY 语句
来定义的,并用 REFERENCES 来指明外码参照的是哪些表的主码。
定义表 SC,其中 Sno 参照表 Student 的主码 Sno,Cno 参照表 Course 的
SNO CHAR(7) 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));
3.用户定义完整性
[例 3]用户定义的属性上的约束条件。
[例 3-1]列值非空。在定义 SC 表时,Sno、Cno 和 Grade 属性都不允许取空值。
在不特别声明的情况下,非码属性的值是允许取空值的。
/*列值非空的约束 NOT NULL*/
[例 3-2]列值唯一。建立部门表 DEPT,要求部门名称 Dname 取值唯一,部门
编号 Deptno 属性为主码。
CREATE TABLE SC(
SNO CHAR(7) NOT NULL,
CNO CHAR(4) NOT NULL,
GRADE
SMALLINT NOT NULL);
CREATE TABLE DEPT(
DEPTNO NUMERIC(7) PRIMARY KEY,
DNAME VARCHAR(9) UNIQUE,
取值唯一*/
LOCATION VARCHAR(10));
CREATE TABLE STUDENT(
SNO
SNAME CHAR(8) NOT NULL,
SSEX
CHAR(7) PRIMARY KEY,
约束条件*/
SMALLINT,
SAGE
SDEPT CHAR(20));
CREATE TABLE SC(
/*UNIQUE 约 束 要 求 Dname
[例 3-3]CHECK 短语指定列值应该满足的条件。定义表 Student,属性 Ssex 的
值只允许取“男”或“女”;定义表 SC,属性 Grade 的值定义在 0-100 之间。
CHAR(2) CHECK(SSEX IN(‘男’,’女’)),
/*CHECK 语句
SNO CHAR(7) NOT NULL,
CNO CHAR(4) NOT NULL,
GRADE SMALLINT CHECK (GRADE>0 AND GRADE<100),
/*CHECK 语句约束
条件*/
PRIMARY KEY (SNO,CNO),
FOREIGN KEY (SNO) REFERENCES STUDENT(SNO),
FOREIGN KEY (CNO) REFERENCES COURSE(CNO));
[例 4]用户定义的元组上的约束条件。
CHECK 短语不光能够定义属性列上的约束条件,还允许用户定义元组级的
约束条件。
定义表 Student,要求当学生性别为男时,其名字不能以 Ms.打头。
CREATE TABLE STUDENT(
SNO CHAR(7) PRIMARY KEY,
SNAME CHAR(8) NOT NULL,
SSEX CHAR(2),SAGE SMALLINT,
SDEPT CHAR(20),CHECK (SSEX = ‘ 女 ’ OR SNAME NOT
/*定义了 Sname 和 Ssex 之间的约束条件*/
LIKE ‘Ms.%’));
4.CONSTRAINT 完整性约束命名子句
[例 5]在定义表时利用约束命名子句对完整性约束条件命名,能够灵活地增加或
删除一个完整性约束条件。
[例 5-1]定义表 Student,要求学号在 90000-99999 之间,姓名不能取空值,年
龄小于 30,性别只能是“男”或“女”。要求全部用约束命名子句实现。
CREATE TABLE STUDENT(
SNO NUMERIC(5)
CONSTRAINT C1 CHECK (SNO BETWEEN 90000 AND 99999),
SNAME VARCHAR(20)
CONSTRAINT C2 NOT NULL,
SAGE NUMERIC(3)
CONSTRAINT C3 CHECK (SAGE < 30),
SSEX VARCHAR(2)
CONSTRAINT C4 CHECK (SSEX IN (‘男’,’女’)),
CONSTRAINT StudentKey PRIMARY KEY(SNO));
在表 Student 上共定义了 5 个约束条件,包括主码约束以及 C1、C2、C3、
C4 四个列级约束。
[例 5-2]修改表 Student 中的完整性限制,去掉对性别的限制,并将年龄的限制
由小于 30 改为小于 40。
ALTER TABLE STUDENT/*去掉对性别的限制条件 C4*/
ALTER TABLE STUDENT/*先删掉原来的约束条件再增加一个新的约束条
DROP CONSTRAINT C4;
件*/
DROP CONSTRAINT C3;
ALTER TABLE STUDENT
ADD CONSTRAINT C3 CHECK(SAGE <40);
5.触发器
触发器可以看成是一类特殊的存储过程,在满足某个特定条件时自动触发执
行,是提高数据库服务器性能的有力工具。
触发器分为三类,更新触发器、插入触发器和删除触发器。
能够定义触发器的用户有:
1) 表的所有者;
2) 系统管理员;
3) 拥有创建触发器的权限,且拥有对操作对象的相应的操作权限的用户。
[例 6]定义表 TAB,并在其上定义触发器 TRI,在对 TAB 的插入和更新后检查,
如果插入或更新的值在 100-1000 之间的话,将值置为 50;如果值大于 1000
的话,则给出新值不允许大于 1000 的提示。
CREATE TABLE tab (col int);
INSERT INTO tab VALUES(10);
INSERT INTO tab VALUES(20);
CREATE TRIGGER tri ON tab AFTER UPDATE , INSERT
AS
BEGIN
DECLARE @new_col
SELECT @new_col=col FROM INSERTED
IF @new_col > 100 AND @new_col < 1000
INT
UPDATE tab
SET col=50 WHERE col=@new_col
IF @new_col > 1000
BEGIN
PRINT ‘New values can not more than 1000’
ROLLBACK TRANSACTION
END
END
检测:1)向表 TAB 插入数据(150)。
执行:INSERT INTO TAB VALUES(150);
结果:插入的数据为 150。值在 100-1000 之间,触发器 TRI 自动
执行,将插入的值置为 50。
2)对表中的数据进行更新,将 20 更新为 1500。
执行:UPDATE TAB SET COL = 1500 WHERE COL = 20;
结果:系统报出‘New values can not more than 1000’的错误,
对表进行查询后发现,表中的数据并没有发生改变。说明在更新数据时,
值大于 1000 则触发触发器 TRI 自动执行,系统报错,更新无效。
[例 7]删除触发器 TRI。
DROP TRIGGER TRI ;
删除触发器 TRI 之后,在对 TAB 进行插入和更新就不再有以上限制了。
五、实验任务
1、使用 T-SQL 命令创建一个表 employees,只含 employeeid、name、sex、birth、
workyear(工作年限)和 education 列,将 name 设为主码,作为列 name 的约束;
对 employeeID 列进行 UNIQUE 约束,并作为表的约束;sex 只能包含男和女;
birth 必须晚于 1980 年 1 月 1 号。
2、使用 alter table 语句为表 employees 添加一个新列 address,并为该列定义 unique
约束。
3、已知表 salary(employeeid,income,outcome)。创建一个表 salary2(employeeid,
income,outcome),要求所有 salary2 表上的 employeeid 列的值都要出现在 salary
表中,利用参照完整性约束实现,要求当删除或修改 salary 表上的 employeeid
列时,salary2 表中的 employeeid 值也随之变化。
(1) 创建 salary
(2) 创建 salary2
a) 创建完 salary2 表后,初始化该表的数据与 salary 表相同。删除 salary 表中一
行数据,再查看 salary2 表的内容,看看会发生什么情况。
答:当删除 salary 表的一行数据后表 Salary2 的数据也会删除。
b) 使用 alter table 语句向 salary 表中的 employeeid 列上添加一个外码,要求当
employees 表中要删除或修改与 employeeid 值有关的行时,检查 salary 表有没
有与该 employeeid 值相关的记录,如果存在,则拒绝更新 employees 表。
4、创建 instead of 触发器,当向 salary 表中插入记录时,先检查 employeeid 列上
的值在 employees 中是否存在,如果存在则执行插入操作,如果不存在则提示“员
工号不存在”。