MySQL数据库的约束

Posted 保护小周ღ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL数据库的约束相关的知识,希望对你有一定的参考价值。

哈喽,大家好!我是保护小周ღ,本期为大家带来的是 mysql 数据库中对表的约束,主要有null (空约束),unique(唯一约束),primary key(主键约束),default(默认值约束), forelgn key(外键约束),check(检查约束),超多实例讲解,通俗易懂。

更多相关知识敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*


一、数据库的约束

1.1数据库的约束类型


1.2 null 约束

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

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

表创建成功,这是插入两条记录观察一下:

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

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

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


1.3 unique (唯一约束)

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

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

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

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

Duplicate entry '1' for key 'id' —— 键“id”的重复条目“1”

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

所以最终只插入了一条记录。


1.4 primary key (主键约束)

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

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

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

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

Duplicate entry '1' for key 'PRIMARY' —— 键“PRIMARY”的重复条目“1”

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

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

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

主键的作用

1)保证实体的完整性;
2)加快数据库的操作速度
3)在表中添加新记录时,DBMS会自动检查新记录的主键值,不允许该值与其他记录的主键值重复。
4)DBMS自动按主键值的顺序显示表中的记录。如果没有定义主键,则按输入记录的顺序显示表中的记录。

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

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

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

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

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


1.5 default (默认值约束)

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

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

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

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

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


1.6 forelgn key (外键约束)

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

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

重点:

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

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

举个例字:

我们先创建这两张表并为成绩表建立外键约束。

学生表 stud 的创建:

成绩表 score 的创建:

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

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

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

语句正常执行没有任何变化。


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

1 80 99 90, 2 74 80 99 , 3 98 78 69 , 4 50 65 56

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

直接报错,不必惊慌,错误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 成绩表有什么影响?

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

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

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

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

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

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

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

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

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

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

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


1.7 check 检查约束

在数据库中,CHECK 约束是指约束表中某一个或者某些列中可接受的数据值或者数据格式。
CHECK 约束可以应用于一个或者多个列,也可以将多个CHECK 约束应用于一个列。
当除去某个表时,对这个表的CHECK 约束也将同时被去除。
在更新表数据的时候,系统会检查更新后的数据行是否满足 CHECK 约束中的限定条件。MySQL 可以使用简单的表达式来实现 CHECK 约束,也允许使用复杂的表达式作为限定条件,例如在限定条件中加入子查询。
设置检查约束时要根据实际情况进行设置,这样能够减少无效数据的输入。

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

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

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

表创建完毕,现在插入两条数据观察观察。

但是我们会发现虽然我们期望 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;

好了好了,关于数据库的约束就浅浅的说一一下啦,关于查询还有许多知识,一篇写不下,下篇博客将着重点将查询的进阶~

至此,Mysql 系列的第四篇内容博主已经分享完了,希望对大家有所帮助,如有不妥之处欢迎批评指正。

本期收录于博主的专栏—— MySQL & JDBC,适用于编程初学者,感兴趣的朋友们可以订阅,查看其它“MySQL 数据库以及Java JDBC 编程的相关知识”。

下一期:MySQL 数据库查询的进阶

感谢每一个观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*

遇见你,所有的星星都落在我的头上……

Mysql六大约束

Mysql基础知识复盘总结

Mysql六大约束(constraint)

约束的作用

在设计表的时候使用约束可以帮助维护表中记录的完整性和有效性

主键约束(PRIMARY KEY)

  • 特点:非空且唯一,每个表只能有一个主键
CREATE TABLE `student`(
	`id` int PRIMARY KEY
);

非空约束(NOT NULL)

CREATE TABLE `student`(
	`id` int NOT NULL
);

唯一约束(UNIQUE)

  • 列级约束用法
CREATE TABLE `student`(
	`id` int UNIQUE
);
  • 表级约束用法
CREATE TABLE `student`(
	`id` int,
	`studentId` int,
	UNIQUE(`id`, `studentId`)
);

默认约束(DEFALUT)

create table `student`(
	`id` int,
	`core` int DEFALUT 1 
);

检查约束(CHECK)

Mysql在Mysql8.0.16以后的版本才提供检查约束
特点:保证字段值满足某一个/多个条件

  • 列级约束用法
CREATE TABLE student(
	`id` int,
	`age` int CHECK(`age` > 0 && `age` <= 120)
);
  • 表级约束用法
CREATE TABLE `user`(
	`id` int,
	`age` int,
	CHECK(`id` < 100 && `age` > 10)
)

外键约束

外键的作用
  1. 外键可以保证数据完整性和一致性,级联操作非常方便;
  2. 使用外键可以将数据完整性判断托付给数据库完成,减少程序的代码量;
外键语法
-- 建表添加外键约束语法
[CONSTRAINT <外键名>] FOREIGN KEY 字段名 [,字段名2,…]
REFERENCES <主表名> 主键列1 [,主键列2,…]
--修改表添加外键约束语法
ALTER TABLE <数据表名> ADD CONSTRAINT <索引名>
FOREIGN KEY(<列名>) REFERENCES <主表名> (<列名>);
-- 删除外键
ALTER TABLE <表名> DROP FOREIGN KEY <外键约束名>;
外键的工作方式
  • 阻止执行
    ① 从表插入新行,其外键值不是主表的主键值便阻止插入;
    ② 从表修改外键值,新值不是主表的主键值便阻止修改;
    ③ 主表删除行,其主键值在从表里存在便阻止删除(要想删除,必须先删除从表的相关行);
    ④ 主表修改主键值,旧值在从表里存在便阻止修改(要想修改,必须先删除从表的相关行)。

  • 级联执行
    ① 主表删除行,连带从表的相关行一起删除。
    ② 主表修改主键值,连带从表相关行的外键值一起修改。

外键的工作方式 - 实例演示
CREATE TABLE `user`(
	`id` int PRIMARY KEY,
	`name` char(50)
);

CREATE TABLE `student`(
	`student_id` int PRIMARY KEY,
	`class` int,
	CONSTRAINT `fk` FOREIGN KEY (`student_id`) REFERENCES `user`(`id`)
);

INSERT INTO `user`
VALUES	(1, "张三"),
		(2, "李四"),
		(3, "王五"),
		(4, "赵六");
			 
			 
INSERT INTO `student`
VALUES	(1, 1),
		(2, 1),
		(3, 2),
		(4, 3);

@ 表1,user表

@ 表2,student表

  • 此时两个表的数据已经被外键约束,执行以下操作:
 1. 操作主表中将被外键约束的数据
	UPDATE `user` SET `id` = 5 WHERE `name` = "张三";  -- SQL报错
	
 2. 操作从表,将被约束的数据修改为主表中<不存在>的外键数据 
	UPDATE `student` SET `student_id` = 5 WHERE `class` = 3;  -- SQL报错
	
 3. 操作从表,将被约束的数据修改为主表中<存在>的外键数据 
	UPDATE `student` SET `student_id` = 4 WHERE `class` = 2;  -- SQL语句通过
  • SQL报错信息(序号与SQL语句相对应)
  1. Cannot delete or update a parent row: a foreign key constraint fails (myDataBase.student, CONSTRAINT fk FOREIGN KEY (student_id) REFERENCES user (id))
  1. Cannot add or update a child row: a foreign key constraint fails (myDataBase.student, CONSTRAINT fk FOREIGN KEY (student_id) REFERENCES user (id))

示例中的三条SQL演示了外键的工作方式中的第②、④点。

外键的缺点
  • 并发问题。在使用外键的情况下,每次修改/删除表数据都需要去另外一个表检查数据,需要获得额外的锁。若是在高并发大流量事务场景,使用外键更容易造成死锁;
  • 扩展性问题。比如从"Mysql"将数据迁移到"Oracle",外键依赖于数据库本身的特性,做迁移可能不方便;
  • 不利于分库分表。在水平拆分和分库的情况下,外键是无法生效的。将数据库关系的维护放入应用程序中,可以为将来的分库分表省去很多的麻烦。

数据库知识补充

什么是级联操作

计算机科学中的级联指的是多个对象之间的映射关系,通过建立数据之间的级联关系可以提高管理效率

数据库水平扩容
  • 水平扩容也叫平行扩容,它的具体做法是以增加节点的方式扩展整个数据库,以达到系统对数据库的需求。简而言之,就是把数据库从已有的数据转移到另一个内存大的数据库当中。
  • 数据在迁移过程中需要满足业务可用和数据不可丢失两个方面。在数据迁移前一定要做好数据备份工作。
数据库垂直扩容
  • “水平”是从左往右的一种方式,那么“垂直”就是一种自上而下的方式,扩容方向不同,难度也不同。
  • 垂直扩容是使用增加内存的方式使得整个系统的容量扩充,扩充难度比较低,不过会受到系统内存的限制,任何系统都有相应的运行内存和存储内存,不可能无限制扩大,当扩大到一定程度的时候就会停止,就要考虑其他方式解决数据库满的问题。

欢迎评论、交流,如若文中描述错误,敬请指导。

以上是关于MySQL数据库的约束的主要内容,如果未能解决你的问题,请参考以下文章

mysql唯一约束

MySQL:MySQL中四大约束

[转]mysql的约束

mysql数据库 check约束无效

mysql-约束概览

MySQL 之约束数据库设计