【MySQL】数据库约束

目录

前言:

一,什么是约束?

二,为什么约束?

三,怎样去约束?

1️⃣非空约束 —— not null

2️⃣默认约束——default

3️⃣唯一约束——unique

4️⃣主键约束——primary key

5️⃣外键约束——foreign key

6️⃣限制约束——check

总结:


前言:

本文我们讨论了数据库约束,我们了解到,数据库约束是一种用于限制存储在数据库表中的数据范围的规则。这些规则可以确保数据的一致性、有效性和可靠性,从而提高整个数据库系统的性能和安全性。详细介绍了常见的数据库约束类型,每种约束类型都有其特定的用途和作用.


一,什么是约束?

在数据库中,约束是一种限制条件,为了确保表中数据的完整性(准确性、正确性),为表添加一些限制。使用约束可以使数据更加准确,约束本质上是对数据的制约和限定条件,是数据库中表设计的一个最基本规则。

二,为什么约束?

约束的作用是保证数据的准确性和完整性。它们可以确保表中的数据符合特定的规则,从而避免了数据冗余和不一致性。数据库约束可以防止在数据库中插入无效或不完整的数据,从而确保数据的完整性。它们还可以帮助确保数据的唯一性,以防止重复数据的出现。

三,怎样去约束?

数据库约束类型

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 nulldefault;发现在插入数据时,即使不手动插入该字段的数据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 nulldefault同时设置的情况下,插入数据时我们可以对该字段不填而采用默认值,且不会报错。但不建议一起使用,通常在必须填入数据的字段中只用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='女')
);


总结:

       在实际应用中,数据库约束对于防止数据冗余、减少数据错误和维护数据完整性至关重要。然而,我们也需要注意不要过度使用约束,因为这可能会影响数据库性能。因此,在使用数据库约束时,我们需要权衡利弊,确保在保证数据质量的同时,不影响系统的正常运行。

       总之,数据库约束是一种强大的工具,可以帮助我们更好地管理和控制数据库中的数据。通过了解不同类型的约束以及如何使用它们,我们可以确保我们的数据库系统更加安全、可靠和高效。希望这篇博客能帮助您更好地理解和应用数据库约束.

   ✨由衷感谢您的阅读,写作是一项漫长而不易的艰辛过程,若能得到您的点赞、评论和关注,作者会由衷感到欣喜。

                                                                   

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值