目录
前言:
本文我们讨论了数据库约束,我们了解到,数据库约束是一种用于限制存储在数据库表中的数据范围的规则。这些规则可以确保数据的一致性、有效性和可靠性,从而提高整个数据库系统的性能和安全性。详细介绍了常见的数据库约束类型,每种约束类型都有其特定的用途和作用.
一,什么是约束?
在数据库中,约束是一种限制条件,为了确保表中数据的完整性(准确性、正确性),为表添加一些限制。使用约束可以使数据更加准确,约束本质上是对数据的制约和限定条件,是数据库中表设计的一个最基本规则。
二,为什么约束?
约束的作用是保证数据的准确性和完整性。它们可以确保表中的数据符合特定的规则,从而避免了数据冗余和不一致性。数据库约束可以防止在数据库中插入无效或不完整的数据,从而确保数据的完整性。它们还可以帮助确保数据的唯一性,以防止重复数据的出现。
三,怎样去约束?
数据库约束类型
NOT NULL | 非空 |
DEFAULT | 默认 |
UNIQUE | 唯一 |
PRIMARY KEY | 主键 |
FOREIGN KEY | 外键 |
CHECK | 限制 |
1️⃣非空约束 —— not null
我们在注册或填表时,有些属性是必填的,不能为空的.
对应到数据库层面,我们在定义表中的每一个字段时,它们有两种可供选择的属性:null(默认的)和 not null(不为空)。数据库字段的默认属性是null,即允许为空;但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。
🔸not null : 要求某一列不能填加空的数据,是给列名来指定的,写到列的后面.
举例:
创建一张Person表,字段包括人的姓名、性别,年龄 且都允许为空
创建一张PersonNotNull表,也包含三个字段:姓名、性别,年龄 但是不都允许为空:
2️⃣默认约束——default
通常在我们注册社交平台时,需要绑定你的手机号,对于电话号码,不同的国家有不同的国际区号。例如,中国的国际区号是+86,如果这个社交媒体平台是中国本土的,则默认中国人使用的最多,所以默认区号就是+86了.
default :规定没有给列赋值的默认值,使用指定列插入的时候,未被指定的列就会按照默认值来填充,如果不修改默认值,那么默认情况下的默认值是 null.
举例:
// 1,创建一张表
mysql> create table if not exists Person(
-> name varchar(20),
-> nationality varchar(20) default '中国',
-> age int(10)
-> );
Query OK, 0 rows affected (0.01 sec)
// 2,将国籍的默认值修改为中国
mysql> desc Person;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| nationality | varchar(20) | YES | | 中国 | |
| age | int(10) | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into Person(name) values ('小白');
Query OK, 1 row affected (0.00 sec)
//3,插入一条数据国籍和年龄字段是默认值
mysql> select * from Person;
+--------+-------------+------+
| name | nationality | age |
+--------+-------------+------+
| 小白 | 中国 | NULL |
+--------+-------------+------+
1 row in set (0.00 sec)
如果 not null 和 default 同时设置,会发生什么呢?
下面这段代码对该问题进行了测试。我们在建表时,同时设定 nationality 字段为not null
和default
;发现在插入数据时,即使不手动插入该字段的数据MySQL也不会报错,而且该字段最终采用了我们设定的默认值.
// 1、新建表,nationality 字段同时设定了not null 和 default
mysql> create table if not exists Person(
-> nationality varchar(20) not null default '中国',
-> age int(10)
-> );
Query OK, 0 rows affected (0.03 sec)
// 2、插入一条数据,nationality 字段不手动插入
mysql> insert into Person (age) values (18);
Query OK, 1 row affected (0.01 sec)
// 3、观察结果,nationality 即使不手动插入也没有报错,且最终插入了默认值
mysql> select * from Person;
+-------------+------+
| nationality | age |
+-------------+------+
| 中国 | 18 |
+-------------+------+
1 row in set (0.00 sec)
总结:在not null
和default
同时设置的情况下,插入数据时我们可以对该字段不填而采用默认值,且不会报错。但不建议一起使用,通常在必须填入数据的字段中只用not null,在事先确定好具体默认值的情况下只用default。
3️⃣唯一约束——unique
unique 唯一,不允许存在两行数据,在这个指定列上重复. 此处的不能重复指的是指定列不同行之间.
举例:
创建一个学生表,把学号设为唯一键并通过一系列插入操作验证唯一键的特性
// 1,创建一张学生表
mysql> create table if not exists Student (
-> id int unique,
-> name varchar(20),
-> age int
-> );
Query OK, 0 rows affected (0.01 sec)
// 2,观察表的结构,唯一字段会被标识 UNI
mysql> desc Student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | UNI | NULL | |
| name | varchar(20) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
// 测试一:唯一字段的数据不能重复
mysql> insert into Student values(20231009,'张三',18);
Query OK, 1 row affected (0.00 sec)
mysql> insert into Student values(20231009,'李四',18);
ERROR 1062 (23000): Duplicate entry '20231009' for key 'id'
// 测试二:唯一字段的数据可以为空
mysql> insert into Student(name,age) values( '张关',19);
Query OK, 1 row affected (0.04 sec)
mysql> insert into Student(name,age) values( '李戴',19);
Query OK, 1 row affected (0.00 sec)
// 3,观察最后结果
mysql> select * from Student;
+----------+--------+------+
| id | name | age |
+----------+--------+------+
| 20231009 | 张三 | 18 |
| NULL | 张关 | 19 |
| NULL | 李戴 | 19 |
+----------+--------+------+
3 rows in set (0.00 sec)
4️⃣主键约束——primary key
主键(primary key) :就是一条数据的身份标识,有助于更容易跟快速的找到表中的一个特定记录.
表的主键有三个特点:
- 一张表只能有一个主键,但一个主键对应一个列.
- 主键字段默认是 not null 属性.
- 主键字段的值不能重复.
🔸主键(primary key) 相当于是 not null 和 unique 的结合,通过 primary key 这个约束指定某一列为主键.
复合主键:
主键是唯一的索引,通常会用ID作为主键,但是并不是每个表都存在ID字段,例如学生表(姓名,生日,性别,班级),这里面每一个值都可能重复,无法使用单一字段作为主键,我们可以将多个字段设置为复合主键,由复合主键标识唯一性。
创建一个Address表,把ip字段和port字段组合成为复合主键,用来标识公网内唯一的一个进程
// 1、新建表,复合主建单独一行写出来
mysql> create table if not exists Address(
-> ip varchar(20),
-> port int unsigned,
-> name varchar(20),
-> primary key(ip, port)
-> );
Query OK, 0 rows affected, 1 warning (0.00 sec)
// 2、查看表结构,发现ip和port字段都标识了PRI
mysql> desc Address;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| ip | varchar(20) | NO | PRI | NULL | |
| port | int(10) unsigned | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
只有复合主键中所有字段的值都一致时,才算主键冲突:
mysql> insert into Address values ('127.0.1', 3030, '张三');
Query OK, 1 row affected (0.01 sec)
mysql> insert into Address values ('127.0.1', 8888, '张三');
Query OK, 1 row affected (0.17 sec)
mysql> select * from Address;
+---------+------+--------+
| ip | port | name |
+---------+------+--------+
| 127.0.1 | 3030 | 张三 |
| 127.0.1 | 8888 | 张三 |
+---------+------+--------+
2 rows in set (0.00 sec)
自增长 —— auto_increment
auto_increment
:设为自增长的字段必须和主键搭配使用,在插入时字段可以不给值,这时自增长属性会自动的被系统触发,从当前表的自增长字段中已经有的最大值进行+1操作,得到一个新的且不同的值。
自增字段的特点:
- 自增长字段必须是整数类型.
- 自增长字段必须是主键或复合主键中的一个字段.
- 一张表最多只能有一个自增长字段.
举例:
创建一张学生表,将学号设为自增长,每次只需指定学生姓名即可,学号按照自增长给出的值分配
我们插入一个叫张三的学生,学号使用自增长给的值,发现自增长初识时默认给的值是1,继续插
入数据,会观察到自增长给的值在原来已有最大值的基础上 + 1.
mysql> insert into Student(name) values('张三');
Query OK, 1 row affected (0.00 sec)
mysql> insert into Student(name) values('李四');
Query OK, 1 row affected (0.00 sec)
mysql> insert into Student(name) values('王五');
Query OK, 1 row affected (0.00 sec)
mysql> insert into Student(name) values('赵六');
Query OK, 1 row affected (0.00 sec)
mysql> select * from Student;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 张三 | NULL |
| 2 | 李四 | NULL |
| 3 | 王五 | NULL |
| 4 | 赵六 | NULL |
+----+--------+------+
4 rows in set (0.00 sec)
当我们插入一个学号为121,姓名为孙钱的学生后,再次插入学生时,观察自增长的前后变化
mysql> insert into Student(id,name) values(121,'孙钱');
Query OK, 1 row affected (0.00 sec)
mysql> insert into Student(name) values('朱敏');
Query OK, 1 row affected (0.00 sec)
mysql> select * from Student;
+-----+--------+------+
| id | name | age |
+-----+--------+------+
| 1 | 张三 | NULL |
| 2 | 李四 | NULL |
| 3 | 王五 | NULL |
| 4 | 赵六 | NULL |
| 121 | 孙钱 | NULL |
| 122 | 朱敏 | NULL |
+-----+--------+------+
6 rows in set (0.00 sec)
结论: 自增长分配值的规律,按照当前已有最大值的基础上 + 1.
5️⃣外键约束——foreign key
两个表之间的数据建立的连接,一个表可以有一个或多个外键
外键用于定义父表和子表之间的关系:外键定义在子表上,父表必须有主键约束或unique约束.
举例:
创建一张班级表,里面有班级号和班级名,在创建一张学生表,里面是学生的姓名和班级号.
用外键将班级表中的班级号和学生表中的班级号联系起来.
// 1,先创建父表
mysql> create table if not exists Class(
-> classId int primary key,
-> className varchar(20)
-> );
Query OK, 0 rows affected (0.01 sec)
//2,子表在创建时,选择自己的某个字段和主表的字段建立外键约束关系
mysql> create table if not exists Student(
-> StudentId int primary key auto_increment,
-> name varchar(20),
-> classId int,
-> foreign key(classId) references class(classId)
-> );
Query OK, 0 rows affected (0.01 sec)
//3,观察父表结构,班级号设为主键
mysql> desc Class;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| classId | int(11) | NO | PRI | NULL | |
| className | varchar(20) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
//4,观察子表结构,从表中 classId 字段信息为MUL,代表将它设为外键
mysql> desc Student;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| StudentId | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| classId | int(11) | YES | MUL | NULL | |
+-----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
我们先在主表(Class)中插入两条班级的信息:
mysql> insert into Class values(20231010,'科文班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into Class values(20231011,'慧通班');
Query OK, 1 row affected (0.00 sec)
mysql> select * from Class;
+----------+-----------+
| classId | className |
+----------+-----------+
| 20231010 | 科文班 |
| 20231011 | 慧通班 |
+----------+-----------+
2 rows in set (0.01 sec)
接下来,我们向子表中插入数据来验证外键的作用
插入一个班级号为 20010321 的学生,MySQL检测到父表中没有这个班级,所以插入失败,这是外键约束起的作用
mysql> insert into Student values(2001032121,'张三丰',20010321);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
(`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classId`) REFERENCES `class`
(`classId`))
从表中外键字段的数据是允许为NULL的。在从表中插入班级id为null的一个学生,意为来了一个新学生,目前还没有分配班级:
mysql> insert into student(name) values ('东皇太一');
Query OK, 1 row affected (0.00 sec)
mysql> select * from student;
+------------+--------------+---------+
| studentId | name | classId |
+------------+--------------+---------+
| 2001032122 | 东皇太一 | NULL |
+------------+--------------+---------+
1 row in set (0.00 sec)
可以看到, 这次插入成功了, 可能有细心的同学会注意到, 明明是第一次成功插入数据, 为什么主键studentId的值不是2, 那是前面尝试添加过一次数据, 但是失败了, 不过自增主键还是增加了.
外键的特点:
- 外键用于关联其他表的主键或唯一键.
- 创建外键约束的时候,是修改子表的代码,父表代码是不受影响的.
- 插入或者修改子表中受约束的这一列数据,就需保证插入/修改后的结果得在父表中存在.
- 删除或修改父表中的数据,需要看这个记录是否在子表中被使用了,如果被使用了,则不能进行删除或修改(约束是双向的).
6️⃣限制约束——check
CHECK 约束用于限制列中的值的范围。(简单认识即可)
如果对单个列定义 CHECK 约束,那么该列只允许特定的值。
如果对一个表定义 CHECK 约束,那么此约束会基于行中其他列的值在特定的列中对值进行限制。
举例:
创建一张身份表,里面有身份id,姓名,以及性别,并且 sex 的值只能为 男 或者 女.
create table if not exists idCard (
id int,
name varchar(20),
sex varchar(1),
check (sex ='男' or sex='女')
);
总结:
在实际应用中,数据库约束对于防止数据冗余、减少数据错误和维护数据完整性至关重要。然而,我们也需要注意不要过度使用约束,因为这可能会影响数据库性能。因此,在使用数据库约束时,我们需要权衡利弊,确保在保证数据质量的同时,不影响系统的正常运行。
总之,数据库约束是一种强大的工具,可以帮助我们更好地管理和控制数据库中的数据。通过了解不同类型的约束以及如何使用它们,我们可以确保我们的数据库系统更加安全、可靠和高效。希望这篇博客能帮助您更好地理解和应用数据库约束.
✨由衷感谢您的阅读,写作是一项漫长而不易的艰辛过程,若能得到您的点赞、评论和关注,作者会由衷感到欣喜。✨