主键&外键

119 阅读4分钟

主键约束:primary key 一定要有

  1. 主键

用于表示数据唯一性的字段,主键 比如学号,身份证,id

  1. 约束

给字段添加限制条件

  1. 主键约束

限制主键字段不能重复,并且不能为空(非空且唯一)

create table table1(
id int primary key auto_increment comment "主键",
name char(50) comment "姓名"
)comment "测试表";
insert into table1 values(1001,'Andy');
insert into table1 values(1002,'Andy');
insert into table1(name) values("Mike");

复合主键

也叫联合主键,由多个字段联合组成的主键,要确保多个字段联合起来非空且唯一

场景:

有可能出现id重复的时候,为了确保唯一性,就可以使用复合组件

比如中间表,两个id会重复,如果插入重复数据,会导致逻辑错误,所以需要设置联合主键

drop table if exists t_s_link;
create table t_s_link(
  t_id int,
  s_id int,
  primary key(t_id,s_id)
);
insert into t_s_link values
(1001,1),
(1001,2),
(1002,1),
(1002,3),
(1002,4);

外键(foreign key)(可空,可不唯一)

作用:用来建立主表和子表之间的关联关系,约束两个表中数据的一致性和完整性

举例:部门表(主表)员工表(子表) 建立了主外键关联,那么在删主表数据的时候,

数据库管理系统会自动检查子表中是否有和主表被删除的这条数据所关联的数据,

如过有,就会禁止删除。

语法:(语法不用背不用记,但是要知道主外键概念即可)

create table 表名 ...字段名 constraint 外面名 foreign key(子表的字段) references 主表名(主键)

更新外键

alter table 表名 add constraint 外键名 foreign key(子表的字段) references 主表名(主键)

删除外键

alter table 表名 drop foregin key 外键名

在定义外键的时候,要遵循以下规则:

  1. 必须要有主表,同时主表一定要有主键,因为是主表的主键去关联子表的外键

  2. 一个表可以有一个或者多个外键,外键可以空值,也可以不唯一

  3. 外键中的列数以及数据类型,必须对应主表的数列数依据数据类型

外键的优势:

  1. 保证了关联表数据的完整和一致性。

  2. 提高数据库的健壮性,不用让应用层的程序员去反复检查数据的完整性和一致性。

  3. 可以实现开发人员和数据库运维人员的分工明确

外键的缺点:

  1. 数据库需要维护外键的内部管理

  2. 有了外键后,你新增,修改,删除的时候,会增加数据库的压力

  3. 容易出现I/O瓶颈

使用外键的推荐方式:

互联网行业

不推荐使用外键,互联网行业数量庞大,很容易出现IO瓶颈

传统行业

管理系统、内部金融系统 数据库数据不会太多,数据库的压力不大。

实际开发中:

大多数情况下不推荐在数据库中设置主外键关联,应在应用层去规避垃圾数据操作。

不应该把压力全部释放到数据库中。

-- 创建部门表(主表)
drop table if exists dept1;
create table dept1(
    id int primary key auto_increment comment "主键",
    d_name char(50) comment "部门名称"
) comment "部门表";
insert into dept1 values(default,"测试部"),(default,"测试部");

-- 创建员工表(子表)
drop table if exists emp1;
create table emp1(
    id int primary key auto_increment comment "主键",
    e_name char(50) comment "员工姓名",
    d_id int comment "部门id",
    constraint fk_emp1_dept1
    foreign key(d_id) references dept1(id)
);

insert into emp1 values
(default,"Andy",1),
(default,"Mike",1),
(default,"Lee",1);
-- 查询 每个部门下面员工的信息
select * from dept1 d  join emp1 e on d.id = e.d_id;
select * from dept1 d left join emp1 e on d.id = e.d_id;
-- 删除软件部
delete from dept1 where id = 1;  -- 会失败 ,因为设置了主外键关联
-- 更新软件部的id
update dept1 set id = 2 where id = 1;  -- 会失败,因为设置主外键关联
update dept1 set d_name = "软件部" where id = 1;  -- 可以操作

联级更新 联级删除

主表操作,子表同步

on update cascade 当主表中的主键或唯一键被更新时,所有从表中引用该键的外键也将被自动更新以匹配新的键值。这有助于保持数据的一致性。

on delete cascade 当主表中的行被删除时,所有从表中引用该主键的外键所对应的行也将被自动删除。这也是一种保持数据一致性的方式

-- 创建部门表(主表)
drop table if exists dept1;
create table dept1(
    id int primary key auto_increment comment "主键",
    d_name char(50) comment "部门名称"
) comment "部门表";
insert into dept1 values(default,"测试部"),(default,"测试部");
-- 创建员工表(子表)
drop table if exists emp1;
create table emp1(
    id int primary key auto_increment comment "主键",
    e_name char(50) comment "员工姓名",
    d_id int comment "部门id",
    constraint fk_emp1_dept1
    foreign key(d_id) references dept1(id)
    on update cascade
    on delete cascade
);
insert into emp1 values
(default,"Andy",1),
(default,"Mike",1),
(default,"Lee",1);