
数据库约束是指对数据库表中的数据所施加的规则或条件,⽤于确保数据的准确性和可靠性。这 些约束可以是基于数据类型、值范围、唯⼀性、⾮空等规则,以确保数据的正确性和相容性。
约束是关系型数据库的一个重要功能主要作用是保证数据的完整性,也可能理解数据的正确性 (数据本身是否正确,关联关系是否正确)
定义表时某列不允许为null时,可以为列添加非空约束。(相当于注册账号时的必填项)
学生名为null时,这条记录是不完整的
drop table if exists student;
create table student(
id bigint,
name varchar(20)
);
# 插⼊数据
insert into student values (1, null);
# 查询
select * from student;drop table if exists student;
# 为所有列添加⾮空约束
create table student (
id bigint,
name varchar(20) NOT NULL
);
# 由于name列有⾮空约束,插⼊NULL值时报错
insert into student values (1, null);NULL列为NO表示值不允许为NULL,YES表示值可以为NULL
desc student;

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

虽然指定了默认约束,但当我们手动指定这一列的值为 NULL 时
插入的值依然是 NULL,因为这个 NULL 是我们自己手动指定的,也可以理解为我们想要的值
用户指定的优先级要高于默认约束
新增年龄列
drop table student;
# 创建学⽣表,加⼊年龄列
create table student (
id bigint,
name varchar(20) not null,
age int
);插入⼀条记录,没有设置默认约束时,不指定年龄的值时列为NULL
insert into student(id, name) values (1, '张三');
select * from student;为年龄的列加入默认约束
drop table student;
# 为年龄列加⼊默认约束
create table student (
id bigint,
name varchar(20) not null,
age int default 18
);插入⼀条记录,不指定年龄的值时列使用了默认值
insert into student(id, name) values (1, '张三');
select * from student;指定了唯⼀约束的列,该列的值在所有记录中不能重复,如⼀个⼈的身份证号,学生的学号等
新增学号列
drop table student;
# 学号列设置唯⼀约束
create table student (
id bigint,
name varchar(20) not null,
age int DEFAULT 18,
sno varchar(10)
);不设置唯⼀约束时,学号可以重复
insert into student(id, name, sno) values (1, '张三', '100001');
insert into student(id, name, sno) values (2, '李四', '100001');
select * from student;为学号列设置唯⼀约束
drop table student;
create table student (
id bigint,
name varchar(20) not null,
age int DEFAULT 18,
sno varchar(10) UNIQUE# 唯⼀约束
);插入重复的学号时报错,唯⼀约束生效
insert into student(id, name, sno) values (1, '张三', '100001');
insert into student(id, name, sno) values (2, ' 李四 ', '100001');
Key列显示UNI表示唯⼀约束

注:
distinct本来数据库服务器存储的内容中,已经有重复的了,展示给用户的时候,展示的是去重的结果
unique 是存的数据就不能重复(重复的数据存不下去),查询的结果自然也是不重复的
主键约束唯⼀标识数据库表中的每条记录。
主键必须包含唯⼀的值,且不能包含null值。
每个表只能有⼀个主键,可以由单个列或多个列组成。
一个主键是多个列(复合主键),在唯一校验时,只有复合主键中的所有列都相同才被判定为相同
通常为每张表都指定⼀个主键,主键列建议使用bigint类型。
相当于:unique + not null

为id列添加非空和唯⼀约束
drop table student;
create table student (
id bigint not null unique,
name varchar(20) not null,
age int DEFAULT 18,
sno varchar(10) UNIQUE
);添加了非空和唯⼀约束之后Key列显示PRI表示主键
desc student;
注意: 当id列的重复时会发生主键冲突
通常把主键列设置为自动增长,让数据库维护主键值
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,这有助于高效地生成唯一标识,保障数据的唯一性和完整性,常与主键约束配合使用。


# 主键列的值为NULL
insert into student(id, name, sno) values (NULL, '张三', '100001');
# 不指定主键
insert into student(name, sno) values ('李四', '100002');

指定列插入和全列插入都会数据库帮助我们处理数据
Extra列显示auto_increment表示自增

注:主键自增一次,数据库就记录了一个id的值,后续每次插入新的数据:id +1(作废的话也会被记录)
# 下⼀次⾃增从主键的最⼤值开始
insert into student(name, sno) values ('钱七', '100005');
select * from student;
1.7主键或唯一键冲突时要有更新操作,冲突更新
INSERT ... ON DUPLICATE KEY UPDATE column = value [, column = value] ...插⼊ID为100,学号为100100的学⽣记录时,报主键冲突
# 插⼊ID为100,学号为100100的学⽣记录时,报主键冲突
insert into student(id, name, sno) values (100, '赵六', '100100');
# 可以使⽤以上语法,如果插⼊时有冲突则更新当前列的值
insert into student(id, name, sno) values (100, '赵六', '100100') ON DUPLICATE KEY UPDATE name = '赵六', sno = '100100';
# 两⾏受影响,表⽰删除了原来的记录,⼜新写⼊了⼀条记录
# 与update student set name = '赵六',sno ='100100'whereid = 100; 等效REPLACE [INTO] table_name
[(column [, column] ...)]
VALUES
(value_list) [, (value_list)] ...
value_list: value, [, value] ...# 写⼊或更新Id为101的记录
REPLACE into student(id, name, sno) values (101, '钱七', '100101');
语法:
CREATE TABLE 表名 (
列1 数据类型,
列2 数据类型,
...,
PRIMARY KEY (列1, 列2, ..., 列N) -- 多个列用逗号分隔,共同作为主键
);但是可以有复合主键
由多个列共同组成的主键,主键是否冲突以多个列的组成进行判定
drop table student;
# 重构学⽣表
create table student (
id bigint,
name varchar(20),
PRIMARY KEY (id, name) # 指定复合主键
);
# 插⼊数据
insert into student(id, name) values (1, '张三');
# 重复插⼊主键冲突,此时主键值由id和name两个列共同决定这个定义方法是错误的
drop table student;
# 重构学⽣表
create table student (
id bigint PRIMARY KEY auto_increment, # 定义主键
name varchar(20) PRIMARY KEY # 定义主键
);外键用于定义主表和从表之间的关系 外键约束主定义在从表的列上,主表关联的列必须是主键或唯⼀约束 当定义外键后,要求从表中的外键列数据必须在主表的主键或唯⼀列存在或为null。

注:
(1)外键约束虽然让我们感觉起来很麻烦,但却是不可缺失的!!!
(2)使用外键约束可以增添校验能力,有效减少错误的发生
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;
语法:
foreign key (id) references class(id)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) # 创建外键约束
);Key列的值为MUL表示外键约束的列

# 班级编号在主表中存在
insert into student(name, class_id) values ('张三', 1), ('李四', 2);
# 插⼊成功
select * from student;
正常插入数据
插入⼀个班级号为100的学生,由于主表中没有这个班级,插入失败
# 班级编号在主表中不存在,提示外键约束限制导致插⼊失败
insert into student(name, class_id) values ('王五', 100);插入班级Id为NULL的记录,可以成功,表示当前学⽣还没有分配置班级
# 班级为NULL
insert into student(name, class_id) values ('王五', NULL);
select * from student;
删除主表某条记录时,从表中不能有对该记录的引用
# 删除从表中没有引⽤的记录,可以成功
delete from class where name = 'go';
select * from class;
# 删除从表中引⽤的记录,失败
delete from class where name = 'java';
删除主表时要先删除从表
# 从表存在是不能删除主表
drop table class;
# 删除从表
drop table student;
# 再删除主表,成功
drop table class;
可以应用于⼀个或多个列,用于限制列中可接受的数据值,从而确保数据的完整性和准确性。 在8.0.16开始全面支持check约束,之前的版本会忽略check的定义
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;
# 插⼊年龄⼩于16岁的记录,失败
insert into student(name, age, gender) values ('张三', 15, '男');
# 插⼊性别的值不是男或⼥的记录,失败
insert into student(name, age, gender) values ('张三', 17, '1');
c1的值不能为0,c2的值必须大于0,c3的值不小于c2
# 列与列之间也可以⽐较,需要在单独⼀⾏中定义
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;
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约束违规错误。