【MySQL】数据库的约束

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 【MySQL】数据库的约束


一、数据库的约束

1.1数据库的约束类型

image.gif编辑


1.2 null 约束

我们在创建表的时候在创建字段的时候可以指定某列不为空,

设计一个学生表 stud ,包含字段 id 类型 varchar(11) , 设置 not null , name 字段,类型 varchar(20)

image.gif编辑 表创建成功,这是插入两条记录观察一下:

image.gif编辑 我们可以观察到 插入第一条数据时,没有报错,当第二条记录企图插入一条 null 值时就报错了。

Column 'id' cannot be null —— 列“id”不能为空

image.gif编辑 当我们企图插入 只有姓名的字段的是否也报错了,字段“id”没有默认值,也是就表示我们不能在id 为空的情况下插入一行记录。show warnings; 可以查看当前的sql语法错误.


1.3 unique (唯一约束)

被指定的该列的记录属性不能重复,比如:每一个人都有自己独有的身份证号,是独一无二的数字组合,所以是不能重复的,在对字段添加该约束后,插入数据时,会根据该字段约束遍历表中的数据,确认没有该字段重复值后方可插入。

设计一个学生表 stud ,包含字段 id 类型 varchar(11) , 设置 unique约束 , name 字段 not null,类型 varchar(20)

image.gif编辑此时我们的 stud 表 id 字段的属性不可重复,name 字段属性 不可为空。

插入3条记录观察观察 : 1 张三, 1 ,李四 , 2, null;

image.gif编辑Duplicate entry '1' for key 'id' —— 键“id”的重复条目“1”

Column 'name' cannot be null —— 列“name”不能为空

image.gif编辑 所以最终只插入了一条记录。


1.4 primary key (主键约束)

有了约束之后,我们创建的表格就会越来越规范,根据博主上面所说,unique 约束字段不可重复,

not null 约束字段不可为空,那这次介绍的 主键约束 primary key 相当于 unique + not null 的约束效果,字段不为空且不可重复。

image.gif编辑重新构建了学生表 stud,并为 id 字段设置了主键约束,

插入3条记录观察观察 : 1 张三, 1 ,李四 , 2, null;

image.gif编辑Duplicate entry '1' for key 'PRIMARY' —— 键“PRIMARY”的重复条目“1”

Column 'name' cannot be null —— 列“name”不能为空

插入:null, 王五 或者 只插入 王五

image.gif编辑image.gif编辑 一个数据表只能有一个主键,一个主键约束也可以针对多个字段创建约束,这样就是多个字段处于不可为空且不可重复的状态。,数据库的主键,指的是一个列或多列的组合,其值能唯一地标识表中的每一行,通过它可强制表的实体完整性。主键主要是用与其他表的外键关联,以及文本记录的修改与删除。

主键的作用

1)保证实体的完整性;

2)加快数据库的操作速度

3)在表中添加新记录时,DBMS会自动检查新记录的主键值,不允许该值与其他记录的主键值重复。

4)DBMS自动按主键值的顺序显示表中的记录。如果没有定义主键,则按输入记录的顺序显示表中的记录。

对于整型(int)的主键,可以搭配自增长 auto_increment 使用,在插入数值时,不给主键字段赋值,主键字段就会根据上一条主键字段的值 + 1。

image.gif编辑插入2条记录观察观察 : 1 张三, null ,李四 。

image.gif编辑 可以看到第一条数据我们对主键 id 插入了数值 1 , 第二条记录,我们对主键 id 插入了数值 null ,正是因为我们对整型主键 id 设置了自增长,所以根据上一个字段的 id 值自增 + 1 = 2;

再插入2条记录观察观察 :100, 王五, null 赵六;

image.gif编辑 这个时候我们可以看到,这个自增属性当面对主动插入时就会失效,当需要自增时还是根据上一条记录的自增字段的值 + 1,所以是赵六的学号是 101, 而不是 3,这个自增属性就像是一个全局变量,可以记录字段的值,输入的时候就赋值,没有赋值的是否就自增。


1.5 default (默认值约束)

当我们对某个字段定义 default 约束的时候,我们在插入记录时,如果忽略该条记录,那么这条记录会按照设置的默认值填充。

例题:重新构建了学生表 stud,并为 sex 字段设置了默认值约束,默认值设置为“男”。

image.gif编辑 数据表构建完毕, 由上表可见,博主设置了三个字段,id , name ,sex ,并将 sex 字段设置默认值约束。

插入2条记录观察观察 : 1 张三 男, 2 李四 。

image.gif编辑image.gif编辑image.gif编辑 第一次我们对第一行记录的所有字段的数据进行插入数据,第二次我们只对第二行记录的 id ,name 字段进行设置,忽略了 sex 字段,但此时我们再对数据表 stud 的数据进行查询的时候发现 第二行记录的sex 字段填充了我们设置的默认值,男。


1.6 forelgn key (外键约束)

作为关系型数据库,外键约束在多表关系中是至关重要的,外键约束主要是关联其他表的主键或者唯一值。语法:

foreign key 【字段名】references 【主表】(主键字段或者唯一字段)

重点:

外键:针对子表,被约束的字段数据,受父字段数据的约束,不可以增改。

外键:针对父表,不能删除修改子表被约束的字段,两表之间约束是双向的。

举个例字:

image.gif编辑 我们先创建这两张表并为成绩表建立外键约束。

学生表 stud 的创建:

image.gif编辑成绩表 score 的创建:

image.gif编辑对子表score 的id 字段与 学生表的id字段产生了外键约束, 学生表为主表。

例题: 对stud 学生表插入数据,观察对score 成绩表有什么影响?

1 张三 男, 2 李四 男 , 3 王小六 女

image.gif编辑 语句正常执行没有任何变化。


例题: 对score 成绩表插入数据,观察对stud 学生表有什么影响?

1 80 99 90

2 74 80 99

3 98 78 69

4 50 65 56

image.gif编辑 当我们插入前三条数据的时候没有任何问题,现在插入第四条数据

image.gif编辑 直接报错,不必惊慌,错误1452(23000):不能添加或更新子行:外键约束失败(' school ')。' score_ibfk_1 ',约束' score_ibfk_1 '外键(' sc_id ')

这是报错信息,意思就是我们不能添加子行,因为受到了主表 stud, stu_id 字段的约束,

外键:针对子表,被约束的字段数据,受父字段数据的约束,不可以增改(改也只能是修改非约束字段)。通俗来讲就是在添加数据或者是修改数据之前,会先遍历父表,如果在父表中找不到约束的关键字,就不允许在子表中进行 insert / update 操作。

所以我们不能在成绩表中添加学号不在 stud学生表中的信息,在创建成绩表的时候我们也对 sc_id 字段设置了主键约束,所以呢, 要想在成绩表中添加记录需要满足以下要求,该记录 sc_id 字段不可为空且不可重复且该记录中的 sc_id字段值必须在 stud 学生表中存在。

此时我们成绩表的操作并不会对我们的主表造成影响。


例题: 对 stud 学生表删除数据修改数据,观察对 score 成绩表有什么影响?

先尝试删除 学生表中的一条记录:

image.gif编辑 错误1451(23000):不能删除或更新父行:外键约束失败(' school ')。' score_ibfk_1 ',约束' score_ibfk_1 '外键(' sc_id ')

报错提示的也非常明显,我们不能修改或删除父行, 因为两表之间存在外键约束。

外键:针对父表,不能删除修改子表被约束的字段,两表之间约束是双向的。

尝试修改学生表中的一条记录:将学生表中的学号为3 的同学的学号修改为 4

image.gif编辑 错误1451(23000):不能删除或更新父行:外键约束失败(' school ')。' score_ibfk_1 ',约束' score_ibfk_1 '外键(' sc_id ')

尝试修改学生表中的一条记录:将学生表中的学号为3 的同学姓名由 王小六 修改为 王六

image.gif编辑修改成功,只要不修改作为外键约束的字段,其他字段的值是可以被修改的。

总结:两表之间或者多表之间存在外键约束,作为主表来讲是不可以随便删除记录的, 那么如何保证数据的有效性呢,比如张三同学已经毕业了,那张三同学的信息就失效了。我们有两种做法,

一:是删除所有与主表与子表有对应字段外键关系的记录,主表是不可删除修改,子表是可以删除的, 我们先将子表中的约束记录删除,主表中的约束字段没有在子表中体现,那么主表中自然是允许删除的,但是有一个缺点就是你无法判断该字段建立了多少外键约束,非要删除的话,需要去找到这些子表,子表与子表之间有可能也存在外键约束,就会非常的复杂。

二:对主表添加可以判断数据是否有效的字段,比如是否毕业,当张三毕业时,我们将该字段设置为已毕业,然后再使用数据时是可以添加条件来约束,例如查找有所未毕业同学的信息,利用条件查询即可。


1.7 check 检查约束

在数据库中,CHECK 约束是指约束表中某一个或者某些列中可接受的数据值或者数据格式。

CHECK 约束可以应用于一个或者多个列,也可以将多个CHECK 约束应用于一个列。

当除去某个表时,对这个表的CHECK 约束也将同时被去除。

在更新表数据的时候,系统会检查更新后的数据行是否满足 CHECK 约束中的限定条件。MySQL 可以使用简单的表达式来实现 CHECK 约束,也允许使用复杂的表达式作为限定条件,例如在限定条件中加入子查询。

设置检查约束时要根据实际情况进行设置,这样能够减少无效数据的输入。

这个约束是啥意思呢,就是指定字段中的数据只能存在于设定的数据范围内,例如:sex 字段 ,

check (sex = "男" or sex = "女")

我们这样限定了之后,就不会出现其他的性别,比如说,"双性",不可能输入,只能存在 “男”或 “女”。比如我们限定了学号的范围 [1,10], 我们的id就只能在这个范围内。

image.gif编辑 表创建完毕,现在插入两条数据观察观察。

image.gif编辑image.gif编辑 但是我们会发现虽然我们期望 check 约束可以将数据限定来我们期望的范围内,但是在添加数据的时候还是可以超出这个限制,原因是因为,不同于SQL,在MYSQL中,CHECK只是一段可调用但无意义的子句。MySQL会直接忽略。 CHECK子句会被分析,但是会被忽略。

说白了就是没用,就是个摆烂的,博主寻思以为自己写错了,特意查询了一波资料,啥用没有,咦~


二、修改表的结构 (alter)

以上约束,可以看到博主都是在创建表的时候添加的( create ),除了我们在创建的时候添加约束,其实还有一种办法就是 修改表的结构 (alter),但是不建议使用吖,因为当我们对已有的表再去修改表的结构的时候会对表中原先存储的数据造成一定程度上的影响,那么我们要添加约束的时候使用修改字段的这个关键字即可 ,就像是创建时的那样,类型后面加上约束。

- 修改字段

   ALTER TABLE test.student MODIFY id_card varchar(30) 【约束】

-- 修改表结构

-- 添加字段

-- 新增一个叫做id_card的字段,它的类型是可变字符串且非空。

   ALTER TABLE test.student ADD id_card varchar(18) NOT NULL;

-- 修改字段

   ALTER TABLE test.student MODIFY id_card varchar(30)

-- 修改字段名

   ALTER TABLE test.student CHANGE id_card id_card1 char(10) not null;

-- 删除字段

   ALTER TABLE test.student DROP id_card1;

-- 修改表名  

   ALTER TABLE test.student RENAME test.stu;


本文图片由保护小周ღ的博客_CSDN博客-C语言,JavaEE,每日一题领域博主提供。

哎,这该死的友谊。

image.gif编辑


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
10 3
|
1天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
12 3
|
1天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
15 2
|
14天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
98 15
|
8天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
15天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
19天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
27天前
|
关系型数据库 MySQL 数据库
GBase 数据库如何像MYSQL一样存放多行数据
GBase 数据库如何像MYSQL一样存放多行数据
|
1月前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
39 1
|
1月前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
61 4