关系完整性是对关系的某种约束,当关系随着时间变化(增删改等操作改变数据库关系表)时应该满足一定的约束条件,通常这些约束条件都依赖于客观事实

关系完整性包含三个方面,分别是

  • 实体完整性
  • 参照完整性
  • 用户自定义完整性

其中实体完整性和参照完整性是关系模型必须满足的约束条件,或者说是所有数据库管理系统都自动支持的约束条件。而用户自定义完整性则是根据不同的应用程序(不同的使用场景)有选择的设置的一些约束条件

实体完整性

实体完整性实际上就是对于主键完整性的约束条件,要求主键不能为空(NULL)。如果主键为空,那么就无法达到唯一标识一个实体的目的了,所以实体完整性应该包含两个约束

  • 不能为NULL
  • 必须唯一,不能重复

实体完整性在SQL语句中使用PRIMARY KEY关键字定义(实际上就是在定义主键)。有两种定义方式,一种是在定义属性的时候将PRIMARY KEY添加到后面,另一种是在定义完所有属性之后使用关键字PRIMARY KEY指出

下面的例子创建一个student表,并将学生id设置为主键(用来设置实体完整性约束)

CREATE TABLE student ( id INT PRIMARY KEY,  /* 紧跟在属性定义后面 */name VARCHAR(20) NOT NULL, sex ENUM('male', 'female'), age INT NOT NULL
);

或者

CREATE TABLE student ( id INT,  name VARCHAR(20) NOT NULL, sex ENUM('male', 'female'), age INT NOT NULL ,PRIMARY KEY(id) /* 在定义完所有属性后设置主键 */
);

另外,考虑另一个表student_course,它存储着所有学生的选课信息,只包含学生id和课程id两个属性,那么根据客观事实可知,想要唯一确定这个表中的某一行,就必须同时提供学生id和课程id,也就是说student_course由(学生id,课程id)这个二元组唯一确定,所以它的主键应该包含两个属性

需要注意的是,当主键包含多个字段时,只能采用上述第二种方式定义主键,对于student_course的表定义如下

CREATE TABLE student_course ( student_id INT NOT NULL, course_id INT NOT NULL, PRIMARY KEY(student_id, course_id) /* 在所有属性定义完后定义主键 */
);

设置之后,当向student表插入数据时,就必须提供一个独一无二的学生id,任何将学生id设置为NULL或者提供了一个重复的id的操作都会报错

参照完整性

参照完整性是相对于外键而言的,在数据库中,外键常用来关联两个表,它的值要么为NULL,要么就是它参照的那个表的主键值。以社交网络系统中的用户实体和分组实体为例,其中

用户实体定义了一个用户的各种信息,包括

  • 用户id
  • 密码
  • 个人信息等

好友分组实体定义了一个分组的信息,包括

  • 分组id
  • 分组名
  • 用户id

这样在查找每个用户的所有分组时只需要将两个表进行联结并且选择用户表的用户id等于分组表的用户id的那几行即可

在上面的设计中,好友分组包含了用户id,它是用户表的主键,像这样的属性被称为外键,它由FOREIGN KEY … REFERENCES关键字定义

CREATE TABLE user (user_id INT AUTO_INCREMENT PRIMARY KEY,password VARCHAR(20) NOT NULL,
);CREATE TABLE groups ( group_id INT AUTO_INCREMENT, group_name VARCHAR(20) NOT NULL, user_id INT, PRIMARY KEY(group_id, group_name),FOREIGN KEY (user_id) REFERENCES user(user_id) /* 将user_id定为外键,参照user表中的user_id属性 */
);

对于外键的约束实际上就是对于参照完整性的约束,对于上面的示例而言,groups表中的user_id字段必须在user表中的user_id字段中存在,也就是不能出现在groups中存在一个user_id它在user中没有的情况

当对表进行插入删除时,数据库管理系统会自动检测该约束规则,常见的情况有两种

  • 向groups表中插入/更新了一行数据,其中的user_id不是user中的数据,就会报错
  • 将user中的某一行数据删除/更新,而groups中存在将要被删除/更新那一行的user_id的数据,则操作被拒绝,同样会报错

上述的两种情况被称为发生了不一致,数据库管理系统有以下几种方式可以处理这种问题

  • 拒绝执行(NO ACTION),不允许这种情况发生,一旦发送,则会报错
  • 级联操作(CASCADE),当删除或更新user表导致发生不一致时,会删除或更新groups表将不一致消除
  • 设置为空值,代替级联对groups表的删除和更新操作,将不一致的外键值设置为NULL

对于级联操作,首先重新定义groups表,为外键user_id设置级联

CREATE TABLE groups ( group_id INT AUTO_INCREMENT, group_name VARCHAR(20) NOT NULL,user_id INT, PRIMARY KEY(group_id, group_name), FOREIGN KEY (user_id) REFERENCES user(user_id) ON DELETE CASCADE /* 表示当user表的某个user_id被删除后,级联删除掉groups表对应数据 */
);

然后为两个表添加数据

mysql> SELECT * FROM user;
+---------+----------+
| user_id | password |
+---------+----------+
|       1 | 1234567  |
|       2 | 1234567  |
|       3 | 1234567  |
+---------+----------+mysql> SELECT * FROM groups;
+----------+------------+---------+
| group_id | group_name | user_id |
+----------+------------+---------+
|        1 | 1_group1   |       1 |
|        1 | 1_group2   |       1 |
|        1 | 1_group3   |       1 |
|        2 | 2_group1   |       2 |
+----------+------------+---------+

现在执行删除操作,删除user表中user_id为1的元组,然后查看groups表,发现和user_id相关的数据也全部被删除

mysql> DELETE FROM user WHERE user_id = 1;
Query OK, 1 row affected (0.02 sec)mysql> SELECT * FROM groups;
+----------+------------+---------+
| group_id | group_name | user_id |
+----------+------------+---------+
|        2 | 2_group1   |       2 |
+----------+------------+---------+

用户自定义完整性

在CREATE TABLE中定义属性时,可以根据应用程序的要求在属性上添加约束条件,即属性限制,包括

  • 列值非空(NOT NULL)
  • 列值唯一(UNIQUE)
  • 检查列值是否满足一个条件表达式(CHECK短语)

比如上述用户表中的密码password属性,很显然不应该允许用户不设置密码,所以在定义这个属性的时候会加上NOT NULL约束

对于CHECK短语,它可以定义在单个属性之后,也可以在所有属性定义完成后再定义,如果是后者,那么条件表达式可以使用任意多个属性进行判断

数据库原理学习笔记(一)关系完整性以及数据库完整性相关推荐

  1. 数据库(学习笔记五)---------什么是数据库脚本?它有什么作用?

    今天我在看一个JSP+Servlet项目的时候,我发现有个在开始写模块代码之前,先好了一个数据库脚本. 要分析需求,创建数据库我是知道的.但是这个Eclipse中的数据库脚本是什么,干什么的呢? 首先 ...

  2. 数据库原理学习笔记(二)数据库范式

    范式可以理解成在设计数据表时的规范级别,常见的范式有 第一范式(1NF) 第二范式(2NF) 第三范式(3NF) BC范式(BCNF) 第一范式 要满足第一范式,要求数据表的每个属性无法再分,也就是需 ...

  3. SQL数据库教程-学习笔记2

    SQL数据库教程-学习笔记2 文章目录 SQL数据库教程-学习笔记2 三.DML语言的学习 1.插入语句:insert into 2.修改语句:update 3.删除语句:delete 4.练习题 四 ...

  4. B站《一天学会 MySQL 数据库》学习笔记

    B站<一天学会 MySQL 数据库>学习笔记 老司机带我飞 职场十字诀:思考.计划.行动.总结.反思 ​关注他 4 人赞同了该文章 登录和退出MySQL服务器 # 登录MySQL $ my ...

  5. Golang底层原理学习笔记(一)

    LCY~~Golang底层原理学习笔记 1 源码调试 go源代码地址:GitHub - golang/go: The Go programming language 1.1 源码编译 现在的go语言大 ...

  6. python爬虫学习笔记2模拟登录与数据库

    前言 为了加入学校里面一个技术小组,我接受了写一个爬取学校网站通知公告的任务.这个任务比以前写的爬虫更难的地方在于,需要模拟登录才能获得页面,以及将得到的数据存入数据库. 本文按照日期来记录我完成任务 ...

  7. 数据库MySQL学习笔记高级篇(周阳)

    数据库MySQL学习笔记高级篇 1. mysql的架构介绍 mysql简介 高级Mysql mysqlLinux版的安装 mysql配置文件 mysql逻辑架构介绍 mysql存储引擎 2. 索引优化 ...

  8. MOOC人工智能原理学习笔记1

    人工智能原理学习笔记1 The Foundations of AI: Philosophy Mathematics Economics Neuroscience Psychology Computer ...

  9. 自控原理学习笔记-系统稳定性分析(2)-环路分析及Nyquist-Bode判据

    自控原理学习笔记 自控原理学习笔记专栏 文章目录 3. 环路分析 3.1环路分析基本思想: 3.2 稳定程度的性能指标(相对稳定) 3.3 环路整形 4.Nyquist判据 4.1 与幅角原理关系 4 ...

最新文章

  1. 课程表美化 css_通过这门11小时的免费课程学习HTML和CSS
  2. 重庆python就业工资待遇-重庆Python人工智能编程
  3. 02 判断某个字符串是否由一个子字符串重复组成
  4. Android渠道包自动发布市场,Android Gradle实现打包指定渠道后自动上传到fir
  5. B端产品经理要掌握的基本功
  6. 【Android 逆向】加壳技术识别 ( VMP 加壳示例 | Dex2C 加壳示例 )
  7. 学习笔记(1):C#Winform水晶报表实例教程-设计带图片的水晶报表
  8. spring 实现小程序抖音去水印后台
  9. linux缺省的shell,Linux操作系统缺省的shell
  10. 怎么通过Win pe下面注册表编辑器载入原来系统注册表更改信息
  11. const char* std::string CString 之间的转换
  12. 【win11】关闭 Windows 安全中心中的Defender 防病毒保护
  13. 炉石传说 疯狂爆破者空场炸死2个精灵龙的概率
  14. Suit and Tie (在线swap 贪心 思维)
  15. canvas实现pc端画板
  16. 客户端开发 Windows驱动开发(1)SDK WDK DDK WDM的关系
  17. 关于Jquery导出word文档
  18. Centos7系统下部署Gitlab+Jenkins+Docker 实现自动化部署项目
  19. 计算机操作系统(第3版)(微课版)课后习题答案全
  20. table动态修改表格内容

热门文章

  1. Java黑皮书课后题第10章:10.24(实现Character类)在Java库中提供了Character类,给出你自己对这个类的实现(将新类命名为MyCharacter)
  2. Java黑皮书课后题第10章:*10.10(Queue类)10.6节给出一个Stock类。设计一个名为Queue的类用于存储整数。像栈一样,队列保存元素。在栈中,元素后进先出。队列中元素先进先出
  3. Validation(2)
  4. cocos creator基础-创建WX开放域遇到的问题
  5. angular2 组件交互
  6. python 皮尔森相关系数
  7. 用程序算法做人生选择
  8. autoreleasing的用法介绍:
  9. I've got so many hongbaos(should it be translated as red bags?)
  10. 我设计的简单事务控制