首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >数据库圣经--约束

数据库圣经--约束

作者头像
Han.miracle
发布2025-12-23 09:51:07
发布2025-12-23 09:51:07
1760
举报

一.什么是数据库约束?

数据库约束是指对数据库表中的数据所施加的规则或条件,⽤于确保数据的准确性和可靠性。这 些约束可以是基于数据类型、值范围、唯⼀性、⾮空等规则,以确保数据的正确性和相容性。

二.约束类型

  • NOT NULL 非空约束:确保指定列不能存储 NULL 值,保证数据的完整性。
  • DEFAULT 默认约束:当列未被赋值时,使用预设的默认值填充。
  • UNIQUE 唯一约束:要求指定列的每行数据值唯一,避免重复。
  • PRIMARY KEY 主键约束:是 NOT NULL 和 UNIQUE 的组合,可指定一列或多列,用于防止数据重复并提升查询性能。
  • FOREIGN KEY 外键约束:定义两个表之间的关联关系,保障数据的完整性和一致性。
  • CHECK 约束:限制列或数据的值,确保数据的准确性和可靠性。

约束是关系型数据库的一个重要功能主要作用是保证数据的完整性,也可能理解数据的正确性 (数据本身是否正确,关联关系是否正确)

1、not null空约束

定义表时某列不允许为null时,可以为列添加非空约束。(相当于注册账号时的必填项)

1.1创建⼀个学生表

学生名为null时,这条记录是不完整的

代码语言:javascript
复制
drop table if exists student;
create table student(
    id bigint,
    name varchar(20)
);
 
# 插⼊数据
insert into student values (1, null);
 
# 查询
select * from student;
1.2此时需要约束学生名的列不能为null
代码语言:javascript
复制
drop table if exists student;
 
# 为所有列添加⾮空约束
create table student (
    id bigint,
    name varchar(20) NOT NULL
);
 
# 由于name列有⾮空约束,插⼊NULL值时报错
insert into student values (1, null);
1.3查看表结构

NULL列为NO表示值不允许为NULL,YES表示值可以为NULL

代码语言:javascript
复制
desc student;
2、default默认值约束

注意:插入时只指定了 Id,这时 name 列使用默认值填充当为某列设置了默认约束的时候,如果不给这个列指定值才会使用默认约束

虽然指定了默认约束,但当我们手动指定这一列的值为 NULL 时

插入的值依然是 NULL,因为这个 NULL 是我们自己手动指定的,也可以理解为我们想要的值

用户指定的优先级要高于默认约束

2.1重构学生表

新增年龄列

代码语言:javascript
复制
drop table student;
 
# 创建学⽣表,加⼊年龄列
create table student (
    id bigint,
    name varchar(20) not null,
    age int
);

插入⼀条记录,没有设置默认约束时,不指定年龄的值时列为NULL

代码语言:javascript
复制
insert into student(id, name) values (1, '张三');
 
select * from student;
2.2重构学生表

为年龄的列加入默认约束

代码语言:javascript
复制
drop table student;
 
# 为年龄列加⼊默认约束
create table student (
    id bigint,
    name varchar(20) not null,
    age int default 18
);

插入⼀条记录,不指定年龄的值时列使用了默认值

代码语言:javascript
复制
insert into student(id, name) values (1, '张三');
 
select * from student;
3、unique唯一约束

指定了唯⼀约束的列,该列的值在所有记录中不能重复,如⼀个⼈的身份证号,学生的学号等

3.1重构学生表

新增学号列

代码语言:javascript
复制
drop table student;
 
# 学号列设置唯⼀约束
create table student (
    id bigint,
    name varchar(20) not null,
    age int DEFAULT 18,
    sno varchar(10)
);

不设置唯⼀约束时,学号可以重复

代码语言:javascript
复制
insert into student(id, name, sno) values (1, '张三', '100001');
 
insert into student(id, name, sno) values (2, '李四', '100001');
 
select * from student;
3.2重构学生表

为学号列设置唯⼀约束

代码语言:javascript
复制
drop table student;
 
create table student (
    id bigint,
    name varchar(20) not null,
    age int DEFAULT 18,
    sno varchar(10) UNIQUE# 唯⼀约束
);

插入重复的学号时报错,唯⼀约束生效

代码语言:javascript
复制
insert into student(id, name, sno) values (1, '张三', '100001');
insert into student(id, name, sno) values (2, ' 李四 ', '100001');
3.3查看表结构

Key列显示UNI表示唯⼀约束

注:

distinct本来数据库服务器存储的内容中,已经有重复的了,展示给用户的时候,展示的是去重的结果

unique 存的数据就不能重复(重复的数据存不下去),查询的结果自然也是不重复的

4、primary key主键约束

主键约束唯⼀标识数据库表中的每条记录。

主键必须包含唯⼀的值,且不能包含null值。

每个表只能有⼀个主键,可以由单个列或多个列组成。

一个主键是多个列(复合主键),在唯一校验时,只有复合主键中的所有列都相同才被判定为相同

通常为每张表都指定⼀个主键,主键列建议使用bigint类型。

相当于:unique + not null

1.1重构学生表

为id列添加非空和唯⼀约束

代码语言:javascript
复制
drop table student;
 
create table student (
    id bigint not null unique,
    name varchar(20) not null,
    age int DEFAULT 18,
    sno varchar(10) UNIQUE
);
1.2查看表结构

添加了非空和唯⼀约束之后Key列显示PRI表示主键

代码语言:javascript
复制
desc student;

注意: 当id列的重复时会发生主键冲突

通常把主键列设置为自动增长,让数据库维护主键值

代码语言:javascript
复制
drop table student;
 
# 重构学⽣表
create table student (
    id bigint PRIMARY KEY auto_increment,  # 设置⾃增主键
    name varchar(20) not null,
    age int DEFAULT 18,
    sno varchar(10) UNIQUE
);
auto_increment

在关系型数据库中,auto_increment 是一个用于自动生成唯一数值的属性,常用于主键列。当为某列设置 auto_increment 后,该列的值会在插入新记录时自动递增,生成唯一的序号,无需手动输入。

例如在 MySQL 中,若将主键列 id 设为 auto_increment,每次插入新数据,id 会自动从当前最大值加 1,这有助于高效地生成唯一标识,保障数据的唯一性和完整性,常与主键约束配合使用。

1.3插入数据时不设置主键列的值
代码语言:javascript
复制
# 主键列的值为NULL
insert into student(id, name, sno) values (NULL, '张三', '100001');
代码语言:javascript
复制
# 不指定主键
insert into student(name, sno) values ('李四', '100002');

指定列插入和全列插入都会数据库帮助我们处理数据

1.4重新查看表结构

Extra列显示auto_increment表示自增

1.5如果使用auto_increment ,某条记录写入失败,新生成的主键值将会作废

注:主键自增一次,数据库就记录了一个id的值,后续每次插入新的数据:id +1(作废的话也会被记录)

1.6主键值可以不连续
代码语言:javascript
复制
# 下⼀次⾃增从主键的最⼤值开始
insert into student(name, sno) values ('钱七', '100005');
 
select * from student;

1.7主键或唯一键冲突时要有更新操作,冲突更新

代码语言:javascript
复制
INSERT ... ON DUPLICATE KEY UPDATE column = value [, column = value] ...

插⼊ID为100,学号为100100的学⽣记录时,报主键冲突

代码语言:javascript
复制
# 插⼊ID为100,学号为100100的学⽣记录时,报主键冲突
insert into student(id, name, sno) values (100, '赵六', '100100');
代码语言:javascript
复制
# 可以使⽤以上语法,如果插⼊时有冲突则更新当前列的值
insert into student(id, name, sno) values (100, '赵六', '100100') ON DUPLICATE KEY UPDATE name = '赵六', sno = '100100';
# 两⾏受影响,表⽰删除了原来的记录,⼜新写⼊了⼀条记录
# 与update student set name = '赵六',sno ='100100'whereid = 100; 等效
1.8替换,如果存在冲突则替换,不存在冲突则插入
代码语言:javascript
复制
REPLACE [INTO] table_name
    [(column [, column] ...)]
VALUES 
    (value_list) [, (value_list)] ...
 
value_list: value, [, value] ...
代码语言:javascript
复制
# 写⼊或更新Id为101的记录
REPLACE into student(id, name, sno) values (101, '钱七', '100101');
1.9表中不能有多个主键,复合主键可以多列

语法:

代码语言:javascript
复制
CREATE TABLE 表名 (
    列1 数据类型,
    列2 数据类型,
    ...,
    PRIMARY KEY (列1, 列2, ..., 列N)  -- 多个列用逗号分隔,共同作为主键
);

但是可以有复合主键

由多个列共同组成的主键,主键是否冲突以多个列的组成进行判定

代码语言:javascript
复制
drop table student;
# 重构学⽣表
create table student (
    id bigint,
    name varchar(20),
    PRIMARY KEY (id, name)  # 指定复合主键
);
 
# 插⼊数据
insert into student(id, name) values (1, '张三');
 
# 重复插⼊主键冲突,此时主键值由id和name两个列共同决定

这个定义方法是错误的

代码语言:javascript
复制
drop table student;
# 重构学⽣表
create table student (
    id bigint PRIMARY KEY auto_increment,  # 定义主键
    name varchar(20) PRIMARY KEY           # 定义主键
);
5、foreign key外键约束

外键用于定义主表和从表之间的关系 外键约束主定义在从表的列上,主表关联的列必须是主键或唯⼀约束 当定义外键后,要求从表中的外键列数据必须在主表的主键或唯⼀列存在或为null。

注:

(1)外键约束虽然让我们感觉起来很麻烦,但却是不可缺失的!!!

(2)使用外键约束可以增添校验能力,有效减少错误的发生

5.1创建班级表(主表),并初始化数据
代码语言:javascript
复制
drop table if exists class;
# 建表
create table class (
    id bigint primary key auto_increment,
    name varchar(20) not null
);
 
# 初始化数据
insert into class (name) values ('java'), ('C'), ('C++'), ('python'), ('go');
 
select * from class;
1.2重构学生表(从表),加入外键约束

语法:

代码语言:javascript
复制
foreign key (id) references class(id)
代码语言:javascript
复制
drop table if exists student;
# 重构表
create table student(
    id bigint PRIMARY KEY auto_increment,  
    name varchar(20) not null,
    age int DEFAULT 18,
    class_id bigint,
    foreign key (class_id) references class(id) # 创建外键约束
);
1.3查看表结构

Key列的值为MUL表示外键约束的列

代码语言:javascript
复制
# 班级编号在主表中存在
insert into student(name, class_id) values ('张三', 1), ('李四', 2);
 
# 插⼊成功
select * from student;

1.4插入数据

正常插入数据

插入⼀个班级号为100的学生,由于主表中没有这个班级,插入失败

代码语言:javascript
复制
# 班级编号在主表中不存在,提示外键约束限制导致插⼊失败

insert into student(name, class_id) values ('王五', 100);

插入班级Id为NULL的记录,可以成功,表示当前学⽣还没有分配置班级

代码语言:javascript
复制
# 班级为NULL
insert into student(name, class_id) values ('王五', NULL);
 
select * from student;
1.5删除记录

删除主表某条记录时,从表中不能有对该记录的引用

代码语言:javascript
复制
# 删除从表中没有引⽤的记录,可以成功
delete from class where name = 'go';
 
select * from class;
代码语言:javascript
复制
# 删除从表中引⽤的记录,失败
delete from class where name = 'java';
1.6删表

删除主表时要先删除从表

代码语言:javascript
复制
# 从表存在是不能删除主表
drop table class;
代码语言:javascript
复制
# 删除从表
drop table student;
 
# 再删除主表,成功
drop table class;
2、check约束

可以应用于⼀个或多个列,用于限制列中可接受的数据值,从而确保数据的完整性和准确性。 在8.0.16开始全面支持check约束,之前的版本会忽略check的定义

  • 定义:CHECK 约束用于保证列中的值符合指定条件。
  • MySQL 中的特殊情况:MySQL 会对 CHECK 子句进行语法分析,但实际会忽略该约束,即 MySQL 不强制执行 CHECK 约束,若需实现类似逻辑,需通过触发器等方式实现。
代码语言:javascript
复制
drop table if exists student;
 
# 加⼊CHECK约束
create table student(
    id bigint PRIMARY KEY auto_increment,  # 设置⾃增主键
    name varchar(20) not null,
    age int DEFAULT 18,
    gender char(1),
    check (age >= 16),
    check (gender = '男' or gender = '⼥')
);
 
# 正常插⼊数据
insert into student(name, age, gender) values ('张三', 17, '男'), ('李四',19,'女');
 
select * from student;
代码语言:javascript
复制
# 插⼊年龄⼩于16岁的记录,失败
insert into student(name, age, gender) values ('张三', 15, '男');
代码语言:javascript
复制
# 插⼊性别的值不是男或⼥的记录,失败
insert into student(name, age, gender) values ('张三', 17, '1');
2.2创建新表

c1的值不能为0,c2的值必须大于0,c3的值不小于c2

代码语言:javascript
复制
# 列与列之间也可以⽐较,需要在单独⼀⾏中定义
create table t_check (
    c1 int check(c1 <> 0),
    c2 int check(c2 > 0),
    c3 int,
    check(c3 >= c2)
);
 
# 插⼊正常数据
insert into t_check values (-1, 3, 10);
 
select * from t_check;
代码语言:javascript
复制
create table t_check (
  c1 int check(c1 <> 0),
  c2 int check(c2 > 0),
  c3 int,
  check(c3 >= c2)
);

insert into t_check values (-1, 3, 10);

select * from t_check;

insert into t_check values (0, 5, 6);

insert into t_check values (2, -10, 10);

insert into t_check values (2, 10, 9);

MySQL 中 CHECK 约束在不同版本有效性的示例。

内容说明
  • 操作与结果:向test_check表插入数据时,符合 CHECK 约束(如性别为 “男”“女”)的记录可成功插入;插入 “无” 时,触发test_check_chk_1约束违规错误。
  • 版本差异:MySQL 8.0 中 CHECK 约束有效,会强制执行数据校验;MySQL 5.7 中 CHECK 约束不生效,需在代码层面(如应用程序逻辑)做数据有效性校验。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.什么是数据库约束?
  • 二.约束类型
    • 1、not null空约束
    • 2、default默认值约束
    • 3、unique唯一约束
    • 4、primary key主键约束
    • 5、foreign key外键约束
    • 2、check约束
    • 内容说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档