数据库约束
目录
约束类型:
一、not null(非空约束):
二、default (默认约束):
三、unique(唯一约束):
四、primary key (主键约束):
单个列主键:
多个列主键:
五、foreign key(外键约束):
示例代码1:
示例代码2:
注意事项:
什么是数据库的约束?
数据库约束是关系型数据库(比如MYSQL)的一个重要功能,主要作用是保证数据的有效性,也可以理解为对数据的正确性进行校验。
约束通常是在创建表时定义的,这是最常见的做法,在表设计阶段,预先规划约束可以确保数据从一开始就符合完整性要求,避免后续脏数据的产生。这是最佳实践。
约束类型:
类型 | 说明 |
not null(非空约束) | 指定非空约束的列不能存储 null 值 |
default (默认约束) | 当没有给列赋值时使用的默认值 |
unique(唯一约束) | 指定唯一约束的列每行数据必须有唯一的值(不能重复,但可以为 null ) |
primary key (主键约束) | not nul 和 unique 的结合,可以指定一个或多个列,有助于防止数据重复和提高数据的查询性能 |
foreign key(外键约束) | 外键约束是一种关系约束,用于定义两个表之间的关联关系,可以确保数据的完整性和一致性 |
check(约束) | 用于限制列或数据在数据库表中的值,确保数据的准确性和可靠性 |
一、not null(非空约束):
定义表时某列不允许为 null 时,可以为列添加非空约束。
假如我们规定学生的 名字 不能为 null :
-- 定义一个学生表
create table student(
id bigint,
name varchar(20) not null
);
-- 添加数据信息
insert into student values (1, null);
添加数据信息这条命令报错,因为学生名字不能为空
正确插入信息:
-- 添加正确的学生信息
insert into student values (1, '张三');
二、default (默认约束):
default 约束用于向列中插入默认值,如果没有为列设置值,那么会将默认值设置到该列。
假如我们学生的 名字 写入时没有指定数据:
-- 定义一个学生表
drop table student;
create table student(
id bigint,
name varchar(20) default '黑名单'
);
-- 插入第一个没有指定名字的学生
insert into student (id) values (1);
-- 插入第二个有指定名字的学生
insert into student (id,name) values (2,'刘棋');
-- 插入第一个没有指定名字的学生
insert into student (id) values (3);
可以看到,第一个和第三个我们没有指定学生的名字,就在设置了默认约束的列加上了 我们创建表时设定的默认值。
三、unique(唯一约束):
用于确保表中某一列值是唯一的,但允许有 null ,比如身份证。
假如我们规定学生的 id 不能 重复:
-- 定义一个学生表
drop table student;
create table student(
id bigint unique;
name varchar(20)
);
-- 插入第一个学生数据
insert into student values (1,'张三');
再往里面插入相同 id 的学生:
insert into student values (1,'王五');
可以看到,id 相同的时候是不行的。
但是 id 可以为 null :
-- id 为 null
insert into student values (null,'王五');
insert into student values (null,'王五');
insert into student values (null,'李四');
只加了 唯一约束 的列可以写入多个 null 。
四、primary key (主键约束):
1. 主键必须包含唯一的值,且不能为 null (唯一且非空)。
2. 每个表只能有一个主键,可以有单个列 或 多个列组成。
3. 一个表只能有一个自增列。
强烈建议每个表中都创建一个主键。
单个列主键:
比如我们创建一个学生表,学生的 id 每个人都是唯一的,且不为 null :
create table student(
id bigint primary key,
name varchar(20)
);
-- 插入第一个学生信息
insert into student (id,name) values (1,'张三');
-- 插入第二个学生信息
insert into student (id,name) values (2,'李四');
如果插入的 id 不唯一 或者 为 null :
-- id 相同
insert into student (id,name) values (1,'李旺');
-- id 为 null
insert into student (id,name) values (null,'李凯');
像这种情况是会报错的,所以,不能这样写。
通常我们把主键列设置为自动增长(auto_increment),让数据库维护主键值:
-- 定义一个学生表
drop table student;
create table student(
id bigint primary key auto_increment,
name varchar(20)
);
-- 插入第一条学生信息
insert into student (name) values ('张三');
-- 插入第二条学生信息
insert into student (name) values ('李四');
-- 插入第三条学生信息
insert into student (id,name) values (null,'王五');
值得注意的是,插入第三个学生信息的时候,我们指定的 id 输入了 null,没有报错,因为在这里 id 是作为占位的存在,写入的 null 只起到占位的作用。
多个列主键:
比如我们想让学生的sno(学生编号)和 name (学生名字)作为主键,可以这么写:
-- 定义一个学生表
drop table student;
create table student(
sno varchar(20),
name varchar(20),
gender bool,
primary key (sno,name)
);
-- 插入第一个学生信息
insert into student (sno,name,gender) values (1,'张三',1);
-- 插入第二个学生信息
insert into student (sno,name,gender) values (2,'张三',1);
-- 插入第三个学生信息
insert into student (sno,name,gender) values (1,'李四',1);
可以看到,当sno 和 name 不是全部相同的时候,可以作为一条数据插入。
但是,这样就会报错:
-- 插入第四个学生信息
insert into student (sno,name,gender) values (1,'张三',10);
因为当多个主键的值组合在一起时,会把当前多个列进行比较,如果主键列都分别相同,就会报错。
再比如一个例子:
CREATE TABLE orders (
user_id INT,
order_id INT,
product_id INT,
PRIMARY KEY (user_id, order_id) -- 复合主键
);
-
合法数据:
(1001, 1, 10)
和(1001, 2, 10)
(user_id
和order_id
的组合唯一)。 -
非法数据:插入两条
(1001, 1, 20)
会因主键重复报错。
实际应用场景:
场景:订单表
-
复合主键设计
CREATE TABLE orders ( user_id INT, order_id INT, product_id INT, PRIMARY KEY (user_id, order_id) -- 确保每个用户的订单ID唯一 );
-
数据库会阻止插入
(1001, 1, 10)
和(1001, 1, 20)
(主键重复),但允许(1001, 1, 10)
和(1002, 1, 10)
。
五、foreign key(外键约束):
1. 外键用于定义主表和从表之间的关系。
2. 外键定义在从表列上,主要关联的列必须是主键或唯一约束。
3. 当定义外键后,要求从表中的外键列数据必须在主表的主键或唯一列存在或为 null 。
从表中使用了主表中的某个值,这个值必须要存在与主表中。
示例代码1:
-- 定义一个班级表(主表)
create table class (
id bigint primary key auto_increment,
name varchar(20) not null
);
-- 定义一个学生表(从表)
create table student (
id bigint primary key auto_increment,
name varchar(20) not null,
class_id bigint,
foreign key (class_id) references class(id) -- 创建外键约束
);
-- 查看 student 表
desc student;
这表明 class_id 列有非唯一索引,因为它是外键。
示例代码2:
create table orders (
order_id INT PRIMARY KEY,
order_date DATE,
customer_id INT,
foreign key (customer_id) references customers(customer_id)
);
上述代码在创建 “orders” 表时,定义了 “customer_id” 为列,通过 “foreign key” 关键字指定,并使用 “references” 关键字指定它引用 “customers” 表中的 “customer_id” 列。
外键约束的注意事项:
数据一致性要求
1.父表的被引用列必须是 主键 或 唯一键。
2. 从表 的外键字段数据类型需与 主表 被引用列完全一致。
注意事项:
-- 定义一个班级表(主表)
create table class (
id bigint primary key auto_increment,
name varchar(20) not null
);
-- 定义一个学生表(从表)
create table student (
id bigint primary key auto_increment,
name varchar(20) not null,
class_id bigint,
foreign key (class_id) references class(id) -- 创建外键约束
);
-- 查看 student 表
desc student;
当删除主表时如果从表中有对主表记录的引用,则不允许删除主表中对应的记录。
比如:
-- 初始化 class 表
insert into class (name) values ('美术班'), ('手工班'), ('数学班'), ('语文班'), ('英语班');
-- 初始化 student 表
insert into student values (1,'张三', 1), (2,'李四', 2),(3,'王五',2),(4,'李琦',5);
然后对其进行删除主表的操作:
-- 删除数学班
delete from class where id = 3;
-- 删除英语班
delete from class where id = 5;
可以看到,数学班删除成功了。
但是英语班由于从表 name = ‘李琦’ 还有关联到这个主表的英语列,所以不能删除。