数据库原理及应用_数据库基础_第4章关系模型的基本理论_数据库完整性规则和MySQL提供的约束

发布于:2025-09-07 ⋅ 阅读:(19) ⋅ 点赞:(0)

前言

        "<数据库原理及应用>(MySQL版)".以下称为"本书"中4.2.1节和4.2.2节内容

引入

        数据库完整性是指数据的正确性和相容性.利用完整性约束,DBMS可帮助用户阻止非法数据的输入

4.2.1 三类完整性规则

        这一小节内容就这样读,也挺抽象.代入两个例子就容易理解了.

1.实体完整性规则

        分析的结果就是规则4.1:主键的各个属性都不能为空值.

2.参照完整性规则

        本书P105中间:参照完整性规则就是定义外键与主键之间的引用规则.

        有几个概念:主键,外键,参照关系和被参照关系.其中主键和外键的概念前面已叙述.参照关系是指:当关系A拥有主键a和外键b.关系B用关系A的外键b作为主键时,称为关系A是参照关系,关系B是被参照关系.如图

关系A 关系B
属性1(主键a) 属性2 属性3(外键b) 属性1(外键b) 属性2

        简单理解:参照关系作为两个关系中的主要关系,先满足关系A,再满足关系B

        规则4.2:外键或者取空值NULL,或者等于被参照关系中的主键的某个值.

        ---规则4.2是结论,通过两个例子去理解.

        例1中的专业号是外键.对于参照关系(学生表)而言,学生可以没选专业(此时是NULL),如果选了专业,其专业号取值必须和被参照关系(专业表)中专业号在同一个域里(必须符合其中一个值).

        例2中参照关系和被参照关系是同一个关系.如果班长没选出来,此项取值NULL.如果选出来了,则必有"班长学号"的取值和主键(学号)取值中的一个值相等.原因班长必是学生中的一员

        一句话总结:外键取值优先,可以为NULL.

3.用户定义完整性规则

        规则4.3 属性的取值应当满足用户定义的约束条件.

综上所述,三类完整性对应了3条规则.这是设计者提出的需求,且由SQL语言提供实现 

本书P105最后一段:DBMS应该提供定义和检验这类完整性的机制(例如约束、触发器等).以便用统一方法来处理它们,而不应该由应用程序来承担这个功能.    

        ---前面帖子中讲过应用程序(高级语言)有丰富的逻辑表达能力和数据控制能力,但是在和数据库交互中,他所做的事是把参数传入SQL,调用SQL函数(通常是SELECT),提取返回值.并不能在建立表和传入表数据时产生各种约束.所以实际上应用程序想承担这个功能都不行.

例4-1 参照完整性规则的变通

        这里是对参照完整性的一点补充:

        1)外键和主键可以不同名,只要值域相同

        ---笔者对此感到困惑.如果外键不同名岂不是会产生误会吗?所以尽量别这样做,保持同名.

        2)依赖关系和参照关系可以是同一个关系

        ---这点前面已经表达过.注意,这里的外键不管是表示"先修"还是"后继",结果都是一样的(他的外键是PC#),PC#取值可以是NULL,或者是C#中的某个值.原因不管先修还是后继课程,都是课程的一种.

        3)外键取值和第2)意思相同.

4.2.2MySQL提供的约束

        包括了主键约束,唯一约束,检查约束,外键约束.

1.主键约束(PRIMARY KEY)

        目的:值唯一,非空

添加方法:见本书P106,P107.推荐使用表级PRIMARY KEY约束.

/*表级主键约束*/
CREATE TABLE employee(
    empno         DECIMAL(2),
    name          VARCHAR(8),
    age           DECIMAL(3),
    deptno        DECIMAL(2),
    CONSTRAINT    pk_no PRIMARY KEY(empno)
);

        调试:不输入empno,不能通过如下图所示

        当输入正确的empno格式后,通过如下图所示

        修改主键约束:创建表后添加主键约束,或者删除主键约束也可以,和表操作相同(ALTER语句)

2.唯一约束

        唯一约束用于候选键的约束.

        候选键本身没多大存在感,他的操作和主键约束差不多,注意可有一个空值(多个属性且无主键),

        建立一个新表employee2,添加唯一约束,phone和name,即表示2个人可以用一个手机号码或者2人可重名

/*表级主键和唯一约束*/
CREATE TABLE employee2(
    empno         DECIMAL(2),
    name          VARCHAR(8),
    age           DECIMAL(3),
    deptno        DECIMAL(2),
    phone         VARCHAR(12),
    CONSTRAINT    pk_no PRIMARY KEY(empno),
    CONSTRAINT    emp_phone UNIQUE(phone,name)
);

        以下是测试结果:

        第5项可以添加是没想到的:两个键组成的唯一约束,两个输入NULL都可以,对于这个情况,一是用得不多不用纠结.二考虑在有主键存在的情况下,唯一约束可以都为空,因为有主键保证唯一性

3.检查约束

        目的:通过检查输入表中的数据来维护用户定义的完整性.

        关键词:CHECK指令

        例4-5:建立employee表,限制age字段的值必须大于20且小于60.

CREATE TABLE employee2(
    empno         DECIMAL(2),
    name          VARCHAR(8),
    age           DECIMAL(3),
    deptno        DECIMAL(2),
    phone         VARCHAR(12),
    CONSTRAINT    pk_no PRIMARY KEY(empno),
    CONSTRAINT    age_CK CHECK(age>20 AND age<60)
);

        输入一个不满足条件的年龄:18,以下是测试结果:

        输入满足条件的年龄:22,以下是测试结果:

        修改检查约束:创建表后添加检查约束,或者删除检查约束也可以,和表操作相同(ALTER语句)

4.外键约束

        本书P109:外键约束涉及两个表,即主表和从表.从表是指外键所在的表,主表是指外键在另一张表中作为主键的表.

        ---这里的两个概念:主表和从表一定要区分清楚.像笔者这样记忆力不好的特别要注意别弄混了.

        主表其实是前面说过的"被参照关系",从表是"参照关系".这里做两点理解:

        1>从表中的外键值受主表限制,可以取NULL或主表中对应的值;

        2>从表的外键值可以相同.

笔者在这里用两个表来说明主表和从表,记住这两个表,很容易对主表和从表做出判定:

学生表(主表) 选课表(从表)
学号(主键) 姓名 性别 出生日期 课程号(主键) 课程名 学号(外键) 成绩
1001 张三 1980/4/30 75001 电影鉴赏 1001 95
1002 李四 1980/8/30 75002 中国古文学 1001 96

        从表的外键值可以相同.在这里的表现就是张三选修了两门课

        此外主表可以看成从表的"基石",从表外键取值必须从主表的主键值中选取(或者NULL)

主表主键操作对从表的影响

        1)插入:无影响

        2)修改:若从表中的外键值与主表中的主键值一样,则有影响

        3)删除:同上,可能有影响

从表外键操作对完整性的影响

        1)插入:受从表主键值的约束

        2)修改:同上,受从表主键值的约束

        3)删除:无影响

主表和从表重在理解,上面的几点不用刻意去记.

例4-6

        建立两个表employee和department,实现两个表的外键约束,并指定级联更新和级联删除

CREATE TABLE department(
    deptno         DECIMAL(5),
    dept_name      VARCHAR(16), 
    CONSTRAINT     dp_no PRIMARY KEY(deptno)
);

CREATE TABLE employee2(
    empno         DECIMAL(5)  PRIMARY KEY,
    ename         VARCHAR(10) NOT NULL,
    age           DECIMAL(3),
    deptno        DECIMAL(5),
    CONSTRAINT    FK_ID FOREIGN KEY(deptno) REFERENCES department(deptno) ON UPDATE CASCADE,
    CONSTRAINT    FK_IG FOREIGN KEY(deptno) REFERENCES department(deptno) ON DELETE CASCADE
);

        注意:这里把级联更新和级联删除放在一起.注意用CONSTRAINT给外键命名时,需要不同的名称,否则报错.

        生成下面两个表

        表1:department(主表)

        表2:employee2(从表)

        然后笔者进行了两步操作:

        1.删除级联更新的外键约束

/*删除级联更新FK_IG*/
ALTER table employee2 DROP FOREIGN KEY FK_IG;

        2.把department中的数据修改

        刷新后NaviCat Premium lite17 崩溃了,重新打开后,表employee2内的数据发生了变化

级联更新发生了,但是把其他数据给删除了,原因暂时未知.

启示

        先不管什么原因造成的,以此看出数据库操作要小心,及时做好备份.每一步操作都能回溯.

修正

        重新建立employee2表如下:

CREATE TABLE employee2(
    empno         DECIMAL(5)  PRIMARY KEY,
    ename         VARCHAR(10) NOT NULL,
    age           DECIMAL(3),
    deptno        DECIMAL(5),
    CONSTRAINT    FK_ID FOREIGN KEY(deptno) REFERENCES department(deptno) ON UPDATE CASCADE
);

        生成数据

        修改department表

        关闭软件再打开软件,点开employee2表

        修改成功

原因探寻

        1.软件问题.这个笔者并不太熟,是可能原因

        2. 是否只允许提交一个外键,多个外键冲突?

        3.从语义上看cascade和set null有冲突.cascade和no action或许可以同时用.有机会可以试试   

小结   

        数据库完整性规则和MySQL提供的约束的一些分析


网站公告

今日签到

点亮在社区的每一天
去签到