当前位置: 首页 > news >正文

MySQL 中数据完整性约束、外键管理(含级联策略) 和多表查询

一、表结构设计与数据完整性约束

数据完整性是数据库设计的核心目标,用于保证数据的准确性、一致性和有效性。代码中通过user(用户表)、dept(部门表)、emp(员工表)的设计,体现了 MySQL 的 5 类核心约束:主键约束、唯一约束、非空约束、检查约束、默认约束。

1. 用户表(user):约束的集中体现

sql

create table user(id int primary key auto_increment comment '主键',name varchar(10) not null unique comment '姓名',age int check (age >= 0 and age <= 120) comment '年龄',status char(1) default '1' comment '状态',gender char(1) comment '性别'
)comment '用户表';

该表是 MySQL约束语法的典型示例,需逐个解析约束的作用:

约束类型字段语法 / 逻辑作用与注意事项
主键约束idprimary key auto_increment- 唯一标识每条用户记录,避免重复;- auto_increment(自增):插入时无需指定id,MySQL 自动生成递增数值(默认从 1 开始),简化操作。
非空约束namenot null强制 “姓名” 必须填写,无法插入namenull的记录(如insert into user(age) values(20)会报错)。
唯一约束nameunique强制 “姓名” 不重复,避免插入同名用户(如已插入Tom1,再插Tom1会报错)。
检查约束agecheck (age >= 0 and age <= 120)限制 “年龄” 范围在 0-120 之间,超出范围的插入会失败(如insert into user(name,age) values('Tom4',150)报错)。⚠️ 注意:MySQL 5.7 及之前版本对check仅语法支持,不实际生效;MySQL 8.0 + 完全支持。
默认约束statusdefault '1'若插入时未指定status值,自动填充为1(如代码中insert into user(name, age, gender) values ('Tom5', 32,'男')Tom5status1)。
2. 部门表(dept)与员工表(emp):关联关系铺垫
  • 部门表(dept:作为 “主表”,存储部门基础信息,id为主键(自增),name非空(部门名称必须存在,避免空部门)。

    sql

    create table dept(id int primary key auto_increment comment 'ID' ,name varchar(50) not null comment '部门名称'  -- 非空:部门必须有名称
    )comment '部门表';
    
  • 员工表(emp:作为 “从表”,与部门表关联(dept_id字段),同时支持 “自关联”(managerid字段,关联自身的id,表示员工的直属领导)。

    sql

    create table emp(id int primary key auto_increment comment 'ID' ,name varchar(50) not null comment '员工姓名' ,  -- 原代码注释笔误,应为“员工姓名”age int comment '年龄',job varchar(20) comment '职位',salary int comment '薪资',entrydate date comment '入职时间' ,  -- date类型:存储年月日(如'2000-01-01')managerid int comment '直属领导ID' ,  -- 自关联字段:关联emp.id(领导也是员工)dept_id int comment '部门ID'  -- 外键字段:关联dept.id(员工所属部门)
    )comment '员工表';
    

    关键字段说明:

    • entrydatedate类型,专门用于存储日期,格式为YYYY-MM-DD,比varchar更节省空间且支持日期函数(如计算入职年限)。
    • managerid:自关联设计的核心,为后续 “查询员工与领导关系” 的自连接查询埋下伏笔。

二、外键管理:维护表间数据一致性

外键(foreign key)是主从表之间的 “纽带”,用于保证从表的外键字段值必须在主表中存在(避免无效关联,如 “员工所属部门不存在”)。代码中完整演示了外键的 “添加、删除、级联策略” 操作。

1. 基本概念:主表与从表
  • 主表:被关联的表(如dept),其主键(dept.id)被从表引用。
  • 从表:引用主表的表(如emp),其外键(emp.dept_id)关联主表主键。
2. 外键操作详解
(1)添加外键

sql

alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);
  • 语法解析:
    • alter table 从表名:修改从表结构。
    • add constraint 外键名:为外键命名(规范:fk_从表名_外键字段名,如fk_emp_dept_id,便于后续管理)。
    • foreign key (从表外键字段):指定从表的外键字段(emp.dept_id)。
    • references 主表名(主表主键):指定关联的主表主键(dept.id)。
  • 作用:插入emp数据时,若dept_id的值在dept.id中不存在(如dept_id=6,但dept中最大id=5),MySQL 会直接报错,拒绝插入。
(2)删除外键

sql

alter table emp drop foreign key fk_emp_dept_id;
  • 语法:通过 “外键名” 删除(而非外键字段名),因为一个表可能有多个外键,需通过名称精准定位。
  • 场景:当需要修改外键策略(如从 “无级联” 改为 “级联删除”)时,需先删除旧外键,再添加新外键。
(3)外键级联策略:主表数据变化时,从表如何联动?

默认情况下,若主表数据被修改 / 删除(如删除dept.id=1的研发部),而从表有依赖该数据的记录(如emp.dept_id=1的员工),MySQL 会直接报错,阻止操作。为解决此问题,需设置级联策略

代码中演示了两种常用级联策略:

  1. 级联更新 / 删除(on update cascade / on delete cascade

    sql

    alter table emp add constraint fk_emp_dept_id 
    foreign key (dept_id) references dept(id) 
    on UPDATE cascade  -- 主表主键更新时,从表外键同步更新
    on DELETE cascade; -- 主表主键删除时,从表关联记录同步删除
    
    • 示例:若将dept.id=1(研发部)更新为id=10,则emp中所有dept_id=1的记录会自动同步为dept_id=10;若删除dept.id=1,则emp中所有dept_id=1的记录会被自动删除。
    • 适用场景:主从表是 “强关联”(如部门删除,下属员工也应删除 / 迁移)。
  2. 更新 / 删除时设为 NULL(on update set null / on delete set null

    sql

    alter table emp add constraint fk_emp_dept_id 
    foreign key (dept_id) references dept(id) 
    on update set null  -- 主表主键更新时,从表外键设为NULL
    on delete set null; -- 主表主键删除时,从表外键设为NULL
    
    • 前提:从表外键字段必须允许为 NULLemp.dept_id未设置not null,符合条件)。
    • 示例:若删除dept.id=1,则emp中所有dept_id=1的记录会自动将dept_id设为NULL(员工仍存在,但暂时无部门)。
    • 适用场景:主从表是 “弱关联”(如部门删除,员工不应被删除,仅解除部门关联)。

三、多表查询:从关联表中提取有效数据

当需要从多个关联表(如empdept)中获取数据时,需使用多表查询。核心是消除笛卡尔积,并根据业务需求选择合适的连接方式(内连接、外连接、自连接)。

1. 基础:笛卡尔积与如何消除
  • 笛卡尔积(Cartesian Product):若直接查询两个表(select * from emp, dept),MySQL 会将emp的每条记录与dept的每条记录强制组合,产生emp行数 × dept行数条记录(如emp有 6 条,dept有 5 条,会产生 30 条无效组合)。
  • 消除方法:通过where子句添加 “关联条件”(如emp.dept_id = dept.id),只保留主从表关联匹配的记录。

代码示例:

sql

-- 消除笛卡尔积,只查员工与所属部门的匹配记录
select * from emp, dept where emp.dept_id = dept.id;
2. 内连接(Inner Join):查询两张表的 “交集”

内连接只返回主从表中关联条件匹配的记录(不匹配的记录会被过滤),是最常用的连接方式,分为 “隐式内连接” 和 “显式内连接”。

(1)隐式内连接(用where关联)

sql

-- 查询员工姓名和所属部门名称(隐式内连接)
select emp.name as 员工姓名, dept.name as 部门名称 
from emp, dept 
where emp.dept_id = dept.id;  -- 关联条件放在where后
  • 特点:语法简洁,但当查询条件复杂时(如多表 + 过滤条件),where子句会混合 “关联条件” 和 “过滤条件”,可读性较差。
(2)显式内连接(用inner join ... on关联)

sql

-- 查询员工姓名和所属部门名称(显式内连接)
select emp.name as 员工姓名, dept.name as 部门名称 
from emp 
inner join dept  -- 明确指定“内连接”
on emp.dept_id = dept.id;  -- 关联条件放在on后
  • 特点:
    • 关键字inner join明确连接类型,on子句单独放关联条件,过滤条件(如where emp.age > 30)可单独放在where后,可读性更强。
    • inner可省略(join默认是内连接),即select ... from emp join dept on ...
  • 结果:仅返回 “有部门的员工” 和 “有员工的部门”(如dept中的 “财务部”(id=3)若没有对应员工,不会出现在结果中)。
3. 外连接(Outer Join):查询 “一张表的全部 + 另一张表的匹配记录”

内连接只查交集,而外连接可查 “某张表的全部记录”(即使另一张表无匹配),分为 “左外连接” 和 “右外连接”。

(1)左外连接(Left Outer Join):左表全部 + 右表匹配

sql

-- 左外连接:查询所有员工(包括无部门的员工),及其所属部门
select emp.*, dept.name as 部门名称 
from emp 
left outer join dept on emp.dept_id = dept.id;  -- left outer join 可简写为 left join
  • 核心规则:
    • 左表from后第一个表(emp),其所有记录都会被返回。
    • 右表join后的表(dept),仅返回与左表匹配的记录;若不匹配,右表字段值为NULL
  • 示例:若emp中有一条dept_id=NULL的员工(如 “临时员工”),左外连接会显示该员工的所有信息,部门名称NULL
  • 简写:left outer join可简化为left join
(2)右外连接(Right Outer Join):右表全部 + 左表匹配

sql

-- 右外连接:查询所有部门(包括无员工的部门),及其下属员工
select dept.name as 部门名称, emp.* 
from emp 
right join dept on emp.dept_id = dept.id;  -- right outer join 可简写为 right join
  • 核心规则:
    • 右表join后的表(dept),其所有记录都会被返回。
    • 左表from后的表(emp),仅返回与右表匹配的记录;若不匹配,左表字段值为NULL
  • 示例:dept中的 “财务部”(id=3)若没有员工,右外连接会显示 “财务部”,emp的所有字段为NULL
  • 关键技巧:右外连接可转换为左外连接(交换表的顺序),如上述右外连接等价于:

    sql

    select dept.name as 部门名称, emp.* 
    from dept 
    left join emp on dept.id = emp.dept_id;  -- 左表为dept,右表为emp
    
4. 自连接(Self Join):将一张表当作 “两张表” 查询

自连接是特殊的多表查询,适用于 “表内存在层级关系” 的场景(如员工与领导的关系,领导也是员工,都存储在emp表中)。核心是给同一张表起两个不同的别名,当作 “两张表”(如 “员工表” 和 “领导表”)。

(1)基础自连接:查询有领导的员工

sql

-- 查询员工姓名及其直属领导姓名(仅显示有领导的员工)
select emp_emp.name as 员工姓名, emp_mgr.name as 领导姓名 
from emp emp_emp, emp emp_mgr  -- 同一张表起两个别名:emp_emp(员工表)、emp_mgr(领导表)
where emp_emp.managerid = emp_mgr.id;  -- 关联条件:员工的managerid = 领导的id
  • 别名意义:
    • emp_emp:代表 “员工” 角色,查询其name
    • emp_mgr:代表 “领导” 角色,查询其name
  • 结果:仅显示有领导的员工(如 “张无忌” 的managerid=1,对应 “金庸”;“金庸” 的managerid=null,无匹配,不显示)。
(2)左外自连接:查询所有员工(包括无领导的)

sql

-- 查询所有员工姓名及其直属领导姓名(无领导的员工也显示)
select emp_emp.name as 员工姓名, emp_mgr.name as 领导姓名 
from emp emp_emp 
left join emp emp_mgr 
on emp_emp.managerid = emp_mgr.id;  -- 左外连接:保留所有员工
  • 结果:“金庸”(managerid=null)会被显示,其领导姓名NULL,符合 “总裁无领导” 的业务逻辑。

四、核心知识点总结

模块核心知识点应用场景
数据完整性约束主键(primary key)、自增(auto_increment)、唯一(unique)、非空(not null)、检查(check)、默认(default)保证数据准确(如年龄 0-120)、不重复(如唯一姓名)、不缺失(如非空姓名)。
外键与级联外键添加 / 删除、级联更新 / 删除(cascade)、级联设为 NULL(set null)维护主从表一致性(如部门删除时,员工不丢失或同步删除)。
多表查询消除笛卡尔积、内连接(交集)、外连接(左 / 右表全部)、自连接(表内层级)复杂业务查询(如查员工 + 部门 + 领导信息、查所有部门及下属员工)。
http://www.dtcms.com/a/462405.html

相关文章:

  • 做效果图的网站有哪些软件有哪些wordpress漂浮
  • 为什么ffmpeg进行视频合成有时长误差
  • 做旅游销售网站平台ppt百度的域名
  • 网站建营销型企业网站有哪些类型
  • 2008服务器网站专门做定制的网站
  • 【软件设计师中级】计算机组成与结构(四):总线系统 - 计算机的“高速公路网络“
  • 专注服务于站长和网站的信息平台.网站建设需要学ps吗
  • 视频直播点播平台EasyDSS推拉流技术结合无人机推流在道路交通巡检场景中的应用
  • 涂鸦T5AI开发板直播互动游戏控制器实现方案【全开源】
  • Spring Boot 应用启动机制详解
  • 河南省建设工程造价协会网站joomla 2.5:你的网站建设_使用与管理 pdf
  • 只有通过Motor 获取 mongodb的collection,才能正常使用 async with collection.watch()监听集合变更
  • 做一个网站 如何盈利网站开发一般用什么软件有哪些
  • 能够完美“适配”不同传感器的语音芯片WT2003H
  • 怎样建设网站的步骤网站建设中js控制什么
  • 陇南地网站建设黄骅市有什么好玩的地方
  • 零基础从头教学Linux(Day 46)
  • RK3588从数据集到训练到部署YoloV8
  • 网站商城建设价格做网站的一定要开80或8080端口
  • STranslate(翻译工具OCR工具) 中文绿色版
  • 算法学习 || 动态规划(买卖股票的最佳时机2)
  • 网站常用图标素材哈尔滨手机网站建设
  • 各种爬虫框架及其特点
  • 架设网站多少钱郑州汉狮做网站的大公司
  • 大厂MySQL数据库规范文档
  • 怎么做网站 高中信息技术锡盟建设工程网站
  • 公司做网站的费用会计分录营销手机软件开发定制
  • 怎么做垂直网站专业营销的网站建设公司哪家好
  • 福田市网站建设推广外包做的网站可以直接去收录吗
  • cynest下料喷漆挡板 exit图形