当前位置: 首页 > news >正文

【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 NULLDEFAULT是处理不同场景的:

  • 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表的约束部分的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!

http://www.lryc.cn/news/604205.html

相关文章:

  • 15-C语言:第15~16天笔记
  • dubbo应用之3.0新特性(响应式编程)(2)
  • 《剑指offer》-算法篇-位运算
  • window weblogic 解锁
  • Object.freeze() 深度解析:不可变性的实现与实战指南
  • 第4章唯一ID生成器——4.5 美团点评开源方案Leaf
  • JVM易混淆名称
  • 【24】C# 窗体应用WinForm ——日历MonthCalendar属性、方法、实例应用
  • 在依赖关系正确的情况下,执行 mvn install 提示找不到软件包
  • 测试自动化不踩坑:4 策略告别 “为自动化而自动化”
  • DPDK PMD 深度解析:高性能网络的核心引擎
  • 使用LangChain构建法庭预定智能体:结合vLLM部署的Qwen3-32B模型
  • 疯狂星期四文案网第23天运营日记
  • 基于Matlab图像处理的静态雨滴去除与质量评估系统
  • 数学建模算法-day[14]
  • LeetCode 刷题【19. 删除链表的倒数第 N 个结点、20. 有效的括号、21. 合并两个有序链表】
  • 面试刷题平台项目总结
  • 用命令查看Android设备的 Linux 内核版本,了解其对应的硬件支持各种特性
  • Git命令保姆级教程
  • 如何进行项目复盘?核心要点分析
  • AI产品经理手册(Ch3-5)AI Product Manager‘s Handbook学习笔记
  • linux命令tail的实际应用
  • C语言---万能指针(void *)、查找子串(strncmp函数的应用)多维数组(一维数组指针、二维数组指针)、返回指针值函数、关键字(const)
  • 【RH134 问答题】第 9 章 访问网络附加存储
  • 什么是数据编排?数据编排的流程、优势、挑战及工具有哪些?
  • OpenLayers 综合案例-底图换肤(变色)
  • Intellij Idea--解决Cannot download “https://start.spring.io‘: Connect timedout
  • 前端路由
  • DAY21 常见的降维算法
  • vulhub 02-Breakout靶场攻略