【MySQL基础篇】:MySQL表的约束常用类型以及实战示例
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨ 文章所属专栏:MySQL篇–CSDN博客
文章目录
- 表的约束
- 1.空属性
- 2.默认值
- 3.列描述
- 4.zerofill
- 5.主键
- 6.自增长
- 7.唯一键
- 8.外键
表的约束
表的约束是数据库中对表中数据完整性进行限制和规范的规则。简单来说,就是给表中的数据设置一些“规范”,确保数据的正确性,一致性和有效性;
约束的核心作用:
- 数据完整性保护:防止无效,错误或不一致的数据进入数据库;
- 业务规则实施:确保数据符合业务逻辑和实际需求;
- 数据一致性维护:保证数据库中的数据始终保持正确的状态;
想象一下生活中的规则:
身份证号必须是18位数字;年龄不能为负数;邮箱地址必须包含@
符号;一个人的身份证号在系统中必须是唯一的等等规则,这些规则就像数据库中的约束,确保数据的“质量”;
约束的工作原理:
约束在以下情况中会发挥作用:
插入数据时:检查新数据是否符合约束条件;
更新数据时:确保修改后的数据仍然满足约束;
删除数据时:某些约束可能会阻止删除操作;
表的约束有很多,这里主要介绍以下几个:null/not null, default, comment, zerofill, primary key, auto_increment, unique_key
。
1.空属性
空属性约束是数据库中最基本也是最常用的约束之一,用来控制字段是否允许存储空值(
NULL
)。
1.NULL和NOT NULL的含义:
NULL(允许空值):
表示该字段可以为空,即不存储任何值(没有数据);
在数据库中,NULL 表示"未知"或"不适用";
NULL 不等于空字符串
''
(即使是空串,那也是“有数据”,只不过数据为空),也不等于数字 0;
NOT NULL(不允许控制):
表示该字段必须有值,不能为空;
插入或更新数据时,该字段必须提供有效值;
如果尝试插入 NULL 值,数据库会报错;
2.基本语法:
-- 创建表时设置约束
CREATE TABLE table_name (column1 datatype NOT NULL,column2 datatype NULL, -- 默认就是 NULL,可以省略column3 datatype -- 不写约束,默认允许 NULL
);-- 修改现有表的约束
ALTER TABLE table_name MODIFY column_name datatype NOT NULL;
ALTER TABLE table_name MODIFY column_name datatype NULL;
3.常用示例:
创建表:
-- 创建一个用户表
mysql> CREATE TABLE users(-> id int,-> name varchar(30) NOT NULL,-> phone varchar(30) NULL-> );
Query OK, 0 rows affected (0.05 sec)-- 查看表结构
mysql> desc users;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | NO | | NULL | |
| phone | varchar(30) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
插入数据:
INSERT INTO users values(1, '张三', '123456');
INSERT INTO users (id, name) values(2, '李四');
INSERT INTO users (id, phone) values(3, '234567');
在第三次插入时,因为name
字段设置了非空属性,所以当我们插入时没有name
字段对应的值就会报错,插入失败;
修改已有字段的约束:
-- 修改name为NULL
mysql> ALTER TABLE users MODIFY name varchar(30) NULL;
Query OK, 0 rows affected (0.10 sec)
Records: 0 Duplicates: 0 Warnings: 0-- 查看表结构
mysql> DESC users;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| phone | varchar(30) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
重新插入:
4.实际应用场景:
必填字段(NOT NULL):
用户信息:用户名、邮箱、密码
订单信息:订单号、用户ID、金额、状态
产品信息:产品名称、价格
系统字段:创建时间、更新时间
可选字段(NULL):
用户信息:手机号、头像、个人简介
订单信息:备注、发货日期、收货地址
产品信息:详细描述、图片URL、标签
2.默认值
1.基本语法:
默认值约束用于在插入数据时,如果没有为某个字段指定值,数据库会自动为该字段填充一个预设的默认值。
-- 创建表时设置约束
CREATE TABLE 表名 (字段名 数据类型 DEFAULT 默认值,...
);-- 给已有默认值的字段修改默认值
ALTER TABLE 表名 MODIFY 字段名 类型 DEFAULT 新的默认值
-- 给已有字段添加默认值
ALTER TABLE 表名 ALTER COLUMN 字段名 SET DEFAULT 默认值;
2.常用示例:
创建表:
mysql> CREATE TABLE student(-> name varchar(30) NOT NULL,-> age tinyint unsigned DEFAULT 0, -- 年龄字段默认值为0-> gender char(2) DEFAULT '男' -- 性别字段默认值为男-> );
Query OK, 0 rows affected (0.05 sec)mysql> DESC student;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint unsigned | YES | | 0 | |
| gender | char(2) | YES | | 男 | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
插入数据:
INSERT INTO student values('张三', 18, '男');
INSERT INTO student (name, gender) values('李四', '女'); -- 插入时省略年龄字段
INSERT INTO student (name, age) values('王五', 20); -- 插入时省略性别字段
修改现有字段的默认值:
mysql> ALTER TABLE student MODIFY age tinyint unsigned DEFAULT 18;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> DESC student;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint unsigned | YES | | 18 | |
| gender | char(2) | YES | | 男 | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)mysql> INSERT INTO student (name, gender) values('赵六', '女'); -- 再尝试插入时省略年龄,此时默认值就变成了18
3.常见场景:
状态字段(如 status、is_active);
时间字段(如 created_at、updated_at);
数值字段(如库存、积分、数量);
标志位(如 is_deleted、is_admin);
4.NOT NULL和DEFAULT之间的关系:
NOT NULL
的作用:
插入时不能插入NULL值
如果尝试插入NULL,会报错
只限制"不能插入什么"
DEFAULT
的作用:
不插入值时会自动插入默认值
只在"没有指定值"时生效
只规定"自动插入什么"
关键点:
NOT NULL
和DEFAULT
是处理不同场景的:
NOT NULL:处理"主动插入NULL"的情况,即使有DEFAULT,如果显式插入NULL,NOT NULL会阻止
DEFAULT:处理"不插入任何值"的情况,只在INSERT语句中完全省略该字段时生效
3.列描述
列描述:comment
,没有什么实际含义,专门用来描述该字段,会根据表创建语句保存,用来给程序员或DBA来进行了解,其实就是平常写代码时的注释;
示例:
创建表:
mysql> CREATE TABLE person(-> name VARCHAR(30) NOT NULL COMMENT '姓名',-> age TINYINT UNSIGNED DEFAULT 18 COMMENT '年龄',-> gender CHAR(2) DEFAULT '男' COMMENT '性别'-> );
通过DESC
查看不到注释信息:
mysql> DESC person;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| age | tinyint unsigned | YES | | 18 | |
| gender | char(2) | YES | | 男 | |
+--------+------------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
通过SHOW
可以看到:
mysql> SHOW CREATE TABLE person \G;
*************************** 1. row ***************************Table: person
Create Table: CREATE TABLE `person` (`name` varchar(30) NOT NULL COMMENT '姓名',`age` tinyint unsigned DEFAULT '18' COMMENT '年龄',`gender` char(2) DEFAULT '男' COMMENT '性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.01 sec)
这个还是挺简单的,没啥好说的,只需要记住是用来当注释的就行了。
4.zerofill
1.基本语法:
zerofill
是用于数值类型字段的一个;当存储的数字位数不足时,自动在数字左侧补零,直到达到指定的显示长度,常用于编号美观。
列名 数据类型(显示长度) ZEROFILL
常与UNSIGNED
一起使用(ZEROFILL
会自动加上UNSIGNED
)。
2.常用示例:
创建表:
mysql> CREATE TABLE test(-> a int(5) ZEROFILL, -- 指定字段a的长度为5位-> b int(8) ZEROFILL -- 指定字段b的长度为8位-> );
Query OK, 0 rows affected, 4 warnings (0.04 sec)-- 查看表结构
mysql> DESC test;
+-------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------------------+------+-----+---------+-------+
| a | int(5) unsigned zerofill | YES | | NULL | |
| b | int(8) unsigned zerofill | YES | | NULL | |
+-------+--------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
-- zerofill自动带上了unsigned
插入数据看效果:
INSERT INTO test values(1,38);
INSERT INTO test values(2,67);
因为字段a是5位,所以长度不足时,会在左侧自动补充0,字段b8位也是如此;
3.注意事项:
- 自动补充的零是在显示时补充的,而不是在数据库中存储时就带上补充的零;
比如上面插入的a=1, b=38
这条数据,查找时通过where a=1
也是可以找到的
mysql> SELECT * FROM test WHERE a = 1;
+-------+----------+
| a | b |
+-------+----------+
| 00001 | 00000038 |
+-------+----------+
1 row in set (0.00 sec)mysql> SELECT * FROM test WHERE a = 00001;
+-------+----------+
| a | b |
+-------+----------+
| 00001 | 00000038 |
+-------+----------+
1 row in set (0.00 sec)
- 显示宽度不是限制实际存储的最大值,只是影响显示效果;
还是上面的例子,字段a的长度为5,不代表存储的最大值只能是5位的
ZEROFILL
只对数值类型有效,比如INT, SMALLINT, BIGINT
等,不能用于字符串类型;ZEROFILL
会自动加上UNSIGNED
既不能存储负数;- 主要用于业务上有编号补零的需求场景,比如订单号,会员号等;
本质上ZEROFILL
就是一种格式化输出而已,还是比较好理解的。
5.主键
1.基本语法:
主键约束用于唯一标识表中的每一行数据;主键字段必须唯一且不能为空(
NOT NULL
).
-- 创建表时指定主键
CREATE TABLE 表名 (字段1 数据类型 PRIMARY KEY, -- 第一种写法字段2 数据类型,...
);CREATE TABLE 表名 (字段1 数据类型,字段2 数据类型,...PRIMARY KEY (字段1) -- 第二种写法
);-- 为已有表添加主键
ALTER TABLE 表名 ADD PRIMARY KEY (字段名);-- 删除主键
ALTER TABLE 表名 DROP PRIMARY KEY;
2.常用示例:
创建表时直接在字段上指定主键:
mysql> CREATE TABLE users(-> id INT UNSIGNED PRIMARY KEY COMMENT '编号为主键',-> name VARCHAR(30) NOT NULL-> );
Query OK, 0 rows affected (0.03 sec)mysql> DESC users;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int unsigned | NO | PRI | NULL | |
| name | varchar(30) | NO | | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
主键约束:主键对应的字段中不能重复,一旦重复,操作失败
INSERT INTO users values(1000, '张三');
INSERT INTO users values(1001, '李四');
INSERT INTO users values(1000, '王五');
删除主键:
mysql> ALTER TABLE users DROP PRIMARY KEY;
Query OK, 2 rows affected (0.09 sec)
Records: 2 Duplicates: 0 Warnings: 0mysql> DESC users;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int unsigned | NO | | NULL | |
| name | varchar(30) | NO | | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
因为主键只有一个,所以删除时不需要具体指明哪个字段,直接删除主键即可;
为已有表添加主键:
mysql> ALTER TABLE users ADD PRIMARY KEY(name); -- 设置name字段为主键
Query OK, 0 rows affected (0.08 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> DESC users;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int unsigned | NO | | NULL | |
| name | varchar(30) | NO | PRI | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
添加主键这里就需要指明具体的哪个字段了;
3.复合主键:
复合主键是指用多个字段的组合来唯一标识一行数据,常用于多对多的中间表。
基本语法:
CREATE TABLE 表名 (字段1 数据类型,字段2 数据类型,...,PRIMARY KEY (字段1, 字段2)
);
示例:
-- 创建表
mysql> CREATE TABLE student(-> student_id INT UNSIGNED NOT NULL,-> course_id INT UNSIGNED NOT NULL,-> name VARCHAR(30) NOT NULL,-> PRIMARY KEY (student_id, course_id) -- 复合主键-> );
Query OK, 0 rows affected (0.04 sec)-- 查看表结构
mysql> DESC student;
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| student_id | int unsigned | NO | PRI | NULL | |
| course_id | int unsigned | NO | PRI | NULL | |
| name | varchar(30) | NO | | NULL | |
+------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
对于复合主键,插入的规则:
-
只有当所有主键字段的组合值都和已有数据完全一样时,才会插入失败;
-
只要有任意一个主键字段的值不同,整个组合就是唯一的,可以插入;
-
单独某一个字段重复没关系,只要组合不重复就行;
插入数据:
-- 先插入一些数据用于后续测试
mysql> INSERT INTO student values-> (1, 1, '张三'),-> (1, 2, '李四'),-> (2, 1, '王五');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0mysql> SELECT * FROM student;
+------------+-----------+--------+
| student_id | course_id | name |
+------------+-----------+--------+
| 1 | 1 | 张三 |
| 1 | 2 | 李四 |
| 2 | 1 | 王五 |
+------------+-----------+--------+
3 rows in set (0.00 sec)-- 开始测试
mysql> INSERT INTO student values(1, 1, '刘备'); -- (1,1)组合存在,插入失败
ERROR 1062 (23000): Duplicate entry '1-1' for key 'student.PRIMARY'
mysql> INSERT INTO student values(2, 1, '关羽'); -- (2,1)组合存在,插入失败
ERROR 1062 (23000): Duplicate entry '2-1' for key 'student.PRIMARY'
mysql> INSERT INTO student values(2, 2, '张飞'); -- (2,2)组合没有出现过,插入成功
Query OK, 1 row affected (0.01 sec)mysql> SELECT * FROM student;
+------------+-----------+--------+
| student_id | course_id | name |
+------------+-----------+--------+
| 1 | 1 | 张三 |
| 1 | 2 | 李四 |
| 2 | 1 | 王五 |
| 2 | 2 | 张飞 |
+------------+-----------+--------+
4 rows in set (0.00 sec)
-
只有所有主键字段的组合完全重复才会插入失败;
-
只要组合唯一,就可以插入,不管单个字段是否重复;
4.注意事项:
一个表只能有一个主键,但主键可以由多个字段组成(复合主键);
主键字段自动带有 NOT NULL 约束(不允许插入空值);
主键字段上的值必须唯一,不能重复;
6.自增长
1.基本语法:
AUTO_INCREMENT
是MySQL中用于让某个整形字段的值自动递增的约束,常用于主键字段;每插入一条新数据,该字段的值会自动加1(或指定步长)。
列名 数据类型 AUTO_INCREMENT
通常配合主键一起使用。
2.常用示例:
- 创建表时设置自增长主键:
mysql> CREATE TABLE users(-> id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,-> name VARCHAR(30)-> );
插入数据时可以不写id
字段,数据库会自动生成:
mysql> INSERT INTO users (name) values ('张三');
Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO users (name) values ('李四');
Query OK, 1 row affected (0.01 sec)mysql> INSERT INTO users (name) values ('王五');
Query OK, 1 row affected (0.00 sec)mysql> SELECT * FROM users;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+----+--------+
如果在某次插入一个较大的id
,下一次自动生成时,会从最大的那个开始加一增长:
mysql> INSERT INTO users values (100, '赵六');
Query OK, 1 row affected (0.01 sec)mysql> INSERT INTO users (name) values ('陈七');
Query OK, 1 row affected (0.01 sec)mysql> SELECT * FROM users;
+-----+--------+
| id | name |
+-----+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
| 100 | 赵六 |
| 101 | 陈七 |
+-----+--------+
5 rows in set (0.00 sec)
- 创建表时指定自增长起始值:
mysql> CREATE TABLE products(-> id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,-> name VARCHAR(30)-> )AUTO_INCREMENT = 1000; -- 自增长初始值从1000开始
Query OK, 0 rows affected (0.04 sec)mysql> DESC products;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)mysql> INSERT INTO products (name) values-> ('苹果'),-> ('香蕉'),-> ('梨子');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0mysql> SELECT * FROM products;
+------+--------+
| id | name |
+------+--------+
| 1000 | 苹果 |
| 1001 | 香蕉 |
| 1002 | 梨子 |
+------+--------+
3 rows in set (0.00 sec)
- 已有表添加自增长:
ALTER TABLE users MODIFY id INT AUTO_INCREMENT;
3.注意事项:
AUTO_INCREMENT
让主键自动递增,简化唯一标识生成;常用于用户表、订单表、商品表等主键字段;
结合
PRIMARY KEY
使用效果最佳;
7.唯一键
一张表中往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键,而唯一键就可以解决表中有很多个字段需要唯一性约束的问题;
唯一键约束用于保证某一列或多列的值在表中是唯一的,既不能有重复值。
1.基本语法:
- 创建表时添加唯一键约束
CREATE TABLE 表名 (列1 数据类型 UNIQUE,列2 数据类型,...
);
- 在已有表中添加唯一键约束
ALTER TABLE 表名 ADD CONSTRAINT 约束名 UNIQUE (列名);
- 为多列添加联合唯一约束
CREATE TABLE 表名 (列1 数据类型,列2 数据类型,...UNIQUE (列1, 列2)
);
2.常用示例:
- 单列唯一约束
-- 创建表
mysql> CREATE TABLE users(-> id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,-> phone VARCHAR(30) UNIQUE -- 单列唯一约束-> );
Query OK, 0 rows affected (0.05 sec)-- 查看表结构
mysql> DESC users;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| phone | varchar(30) | YES | UNI | NULL | |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)-- 插入数据
mysql> INSERT INTO users values(100, '123456');
Query OK, 1 row affected (0.01 sec) -- 插入成功mysql> INSERT INTO users values(1001, '123457');
Query OK, 1 row affected (0.01 sec) -- 插入成功-- 查询
mysql> SELECT * FROM users;
+------+--------+
| id | phone |
+------+--------+
| 100 | 123456 |
| 1001 | 123457 |
+------+--------+
2 rows in set (0.00 sec)-- 插入重复的值
mysql> INSERT INTO users values(1002, '123456');
ERROR 1062 (23000): Duplicate entry '123456' for key 'users.phone' -- 插入失败-- 唯一约束允许插入NULL 并且可以插入多个NULL NULL不做唯一性比较
mysql> INSERT INTO users values(1003, NULL);
Query OK, 1 row affected (0.01 sec)mysql> SELECT * FROM users;
+------+--------+
| id | phone |
+------+--------+
| 1003 | NULL |
| 100 | 123456 |
| 1001 | 123457 |
+------+--------+
3 rows in set (0.00 sec)
- 多列联合唯一约束
-- 建立表
mysql> CREATE TABLE orders(-> id INT PRIMARY KEY AUTO_INCREMENT,-> user_id INT,-> product_id INT,-> UNIQUE (user_id, product_id) -- 多列联合唯一约束-> );
Query OK, 0 rows affected (0.04 sec)-- 查看表结构
mysql> DESC orders;
+------------+------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| user_id | int | YES | MUL | NULL | |
| product_id | int | YES | | NULL | |
+------------+------+------+-----+---------+----------------+
3 rows in set (0.00 sec)-- 插入数据
mysql> INSERT INTO orders values(100, 10, 1001);
Query OK, 1 row affected (0.01 sec) -- 组合(10, 1001)不存在,插入成功mysql> INSERT INTO orders values(101, 11, 1002);
Query OK, 1 row affected (0.00 sec) -- 组合(11, 1002)不存在,插入成功mysql> INSERT INTO orders values(102, 11, 1003);
Query OK, 1 row affected (0.01 sec) -- 组合(11, 1003)不存在,插入成功mysql> INSERT INTO orders values(103, 12, 1003);
Query OK, 1 row affected (0.00 sec) -- 组合(12, 1003)不存在,插入成功mysql> INSERT INTO orders values(104, 12, 1003);
ERROR 1062 (23000): Duplicate entry '12-1003' for key 'orders.user_id' -- 组合(12, 1003)存在,插入失败
mysql> SELECT * FROM orders;
+-----+---------+------------+
| id | user_id | product_id |
+-----+---------+------------+
| 100 | 10 | 1001 |
| 101 | 11 | 1002 |
| 102 | 11 | 1003 |
| 103 | 12 | 1003 |
+-----+---------+------------+
4 rows in set (0.00 sec)
多列联合约束时,插入的规则其实和复合主键那里差不多;
3.注意事项:
主键和唯一键的区别:
- 主键更多的是标识唯一性的,而唯一键更多的是保证在业务上,不要和别的信息出现重复;
- 主键自带
NOT NULL
属性,不允许为空,而唯一键允许为空,并且可以多个为空,因为NULL
不做唯一性比较;
8.外键
外键约束用于在两张表之间建立关联,保证数据的完整性和一致性;
外键(Foreign Key)是指在一张表中的某个字段,它引用了另一张表的主键(或唯一键);
这样可以确保被引用的值在主表中一定存在,防止“孤儿数据”。
1.基本语法:
- 创建从表时添加外键
CREATE TABLE 从表 (字段1 数据类型,字段2 数据类型,...外键字段 数据类型,FOREIGN KEY (外键字段) REFERENCES 主表(主键字段)
);
- 已有从表上添加外键
ALTER TABLE 从表
ADD CONSTRAINT 外键名 FOREIGN KEY (外键字段) REFERENCES 主表(主键字段);
2.常用示例:
- 创建主表和从表
-- 主表
mysql> CREATE TABLE class(-> id INT PRIMARY KEY,-> classname VARCHAR(30)-> );
Query OK, 0 rows affected (0.04 sec)-- 从表
mysql> CREATE TABLE student(-> id INT PRIMARY KEY,-> name VARCHAR(30),-> class_id INT,-> FOREIGN KEY (class_id) REFERENCES class(id) -- 通过class_id相关联-> );
Query OK, 0 rows affected (0.06 sec)-- 查看表结构
mysql> DESC student;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(30) | YES | | NULL | |
| class_id | int | YES | MUL | NULL | |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
说明:student
表的class_id
字段和class
表的id
字段形成关联的关系,这就是外键约束。
- 插入数据
先正确插入班级数据:
mysql> INSERT INTO class values-> (1, '软件工程1班'),-> (2, '软件工程2班');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0mysql> SELECT * FROM class;
+----+------------------+
| id | classname |
+----+------------------+
| 1 | 软件工程1班 |
| 2 | 软件工程2班 |
+----+------------------+
2 rows in set (0.00 sec)
再插入学生数据:
mysql> INSERT INTO student values (1001, '张三', 1); -- 1班存在,插入成功
Query OK, 1 row affected (0.01 sec)mysql> INSERT INTO student values (1002, '李四', 2); -- 2班存在,插入成功
Query OK, 1 row affected (0.01 sec)mysql> INSERT INTO student values (1003, '王五', 3); -- 3班不存在,插入失败
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test1`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))mysql> SELECT * FROM student;
+------+--------+----------+
| id | name | class_id |
+------+--------+----------+
| 1001 | 张三 | 1 |
| 1002 | 李四 | 2 |
+------+--------+----------+
2 rows in set (0.00 sec)mysql> INSERT INTO student value (1004, '赵六', NULL); -- 插入班级为空,插入成功
Query OK, 1 row affected (0.01 sec)mysql> SELECT * FROM student;
+------+--------+----------+
| id | name | class_id |
+------+--------+----------+
| 1001 | 张三 | 1 |
| 1002 | 李四 | 2 |
| 1004 | 赵六 | NULL |
+------+--------+----------+
3 rows in set (0.01 sec)
3.理解外键约束:
在这个世界中,很多数据都是有相关性的,理论上,在上面的例子中,即使不创建外键约束,正常建立学生表和班级表,该有的字段也都有;
但是在实际生活使用中,可能会出现插入的学生信息中有具体的班级,但是该班级却不在班级表中,很明显这是有问题的;
因为此时两张表在业务上是有相关性的,但是在业务上却没有建立约束关系,所以就可能出现各种问题;
因此外键约束就可以很好地把表和表之间在业务上关联起来,本质上外键就是把相关性交给mysql去审核了,提前告诉mysql表之间的约束关系,那么当用户插入不符合业务逻辑的数据时,mysql就会不允许插入,导致插入失败;
4.注意事项:
外键字段类型必须与主表被引用字段类型一致;
被引用的字段必须是主键或唯一键;
外键约束需要存储引擎为InnoDB(MyISAM不支持外键);
以上就是关于MySQL表的约束部分的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!