8.MySql约束

1 阅读5分钟

概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。目的:保证数据库中数据的正确、有效性和完整性。

约束描述关键字
非空约束限制该字段的数据不能为nullNOT NULL
唯一约束保证该字段的所有数据都是唯一、不重复的UNIQUE
主键约束主键是一行数据的唯一标识,要求非空且唯一PRIMARY KEY
默认约束保存数据时,如果未指定该字段的值,则采用默认值DEFAULT
检查约束(8.0.16版本之后)保证字段值满足某一个条件CHECK
外键约束用来让两张表的数据之间建立连接,保证数据的一致性和完整性FOREIGN KEY

A.创建tb_user 表生成id字段为主键自增,name 不为空,不重复,年龄大于0小于120,状态默认值为1,性别无限制

create table tb_user(
    id int AUTO_INCREMENT PRIMARY KEY comment 'ID唯一标识',
    name varchar(20) NOT NULL UNIQUE comment '姓名(不为空,不重复)',
    age int CHECK ( age > 0 && age < 120  )comment '年龄',
    status int DEFAULT '1' comment '状态',
    gender char(1)  comment '性别'
)

插入值测试验证

insert into tb_user(name,age,status,gender) values
    ('Tom1',19,'1','男'),
    ('Tom2',25,'0','男');

insert into tb_user(name,age,status,gender) values 
    ('Tom3',19,'1','男');
insert into tb_user(name,age,status,gender) values (null,19,'1','男');

Column 'name' cannot be null 因为 NOT NULL约束name 不能为空

insert into tb_user(name,age,status,gender) values ('Tom3',19,'1','男');

Duplicate entry 'Tom3' for key 'tb_user.name' 因为name设置了UNIQUE 数据库发现表中已经存在一条 name 为 'Tom3' 的记录,因此拒绝插入这条重复数据

insert into tb_user(name,age,status,gender) values ('Tom5',-1,'1','男');

Check constraint 'tb_user_chk_1' is violated. 违反检查约束

外键约束

外键:用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。

我们先创建一个tb_game 记录游戏名称 关联 honor_of_kings_hero 角色表 做到角色和游戏关联

-- 创建游戏表
create  table tb_game(
    id int AUTO_INCREMENT PRIMARY KEY comment 'ID唯一标识',
    name varchar(20) NOT NULL UNIQUE comment '游戏名称'
)comment '游戏表';
-- 添加数据
insert into tb_game(name) values ('王者荣耀'),('英雄联盟');

-- 给角色添加游戏ID
alter table honor_of_kings_hero add column game_id int comment '游戏ID';
-- 将现在王者荣耀的角色设置game_id=1
update honor_of_kings_hero set game_id=1;

insert into honor_of_kings_hero(name,gender,age,faction,release_date,game_id) values
    ('发条魔灵','女',28,'皮尔特沃夫','2011-06-01',2),
   ('德玛西亚之力','男',30,'德玛西亚','2010-04-27',2);

目前上述两张表,只是在逻辑上存在这样一层关系;在数据库层面,并未建立外键关联,所以是无法保证数据的一致性和完整性的,也就是如果我们删除了游戏表中的一条数据角色表中game_id 对应对应字段还存在但是已经没有关联关系了

1). 添加外键 语法CREATE TABLE 表名( 字段名 数据类型, ... [CONSTRAINT] [外键名称] FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名) );

ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名) ;

为db_game 和 honor_of_kings_hero 添加外键

alter table honor_of_kings_hero add constraint fk_hkh_game foreign key (game_id) references tb_game(id);

image.png

执行删除db_game一条数据

添加了外键约束之后,我们再到dept表(父表)删除id为1的记录,然后看一下会发生什么现象。 此时将会报错,不能删除或更新父表记录,因为存在外键约束。

Cannot delete or update a parent row: a foreign key constraint fails(db_04.honor_of_kings_hero, CONSTRAINT fk_hkh_game FOREIGN KEY (game_id) REFERENCES tb_game (id))

2). 删除外键ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;

-- 删除外键
alter table honor_of_kings_hero drop foreign key fk_hkh_game;

删除/更新行为

添加了外键之后,再删除父表数据时产生的约束行为,我们就称为删除/更新行为。具体的删除/更新行为有以下几种:

行为说明
NO ACTION当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。 (与 RESTRICT 一致) 默认行为
RESTRICT当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。 (与 NO ACTION 一致) 默认行为
CASCADE当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录。
SET NULL当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(这就要求该外键允许取null)。
SET DEFAULT父表有变更时,子表将外键列设置成一个默认的值 (Innodb不支持)

具体语法为: ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段) REFERENCES 主表名 (主表字段名) ON UPDATE CASCADE ON DELETE CASCADE;

1). CASCADE

alter table honor_of_kings_hero add constraint fk_hkh_game foreign key (game_id) references tb_game(id) on update cascade on delete cascade;

image.png

原始数据

image.png image.png

修改主表(主表id改为3后子表game_id也改变了)

image.png

image.png

B. 删除父表id为3的记录 子表也会删除

2). SET NULL

在进行测试之前,我们先需要删除上面建立的外键 fk_hkh_game。然后再通过数据脚本,将 honor_of_kings_hero、db_game表的数据恢复了。

alter table honor_of_kings_hero add constraint fk_emp_dept_id foreign key (game_id) references
tb_game(id) on update set null on delete set null ;
delete from tb_game where id=2;

接下来,我们删除id为2的数据,看看会发生什么样的现象。

image.png honor_of_kings_hero 的game_id 值都为null了