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

SQL-多表查询

一、MySQL 中的多表查询

多表查询是指在一个 SQL 查询语句中同时涉及两个或多个数据表,通过表之间的关联关系(通常是外键)获取跨表的数据。

核心问题:笛卡尔积当直接查询多个表而不添加关联条件时,会产生 “笛卡尔积” 现象 —— 即第一个表的每一行与第二个表的每一行强制组合,结果集的行数是两个表行数的乘积(如 A 表 3 行、B 表 4 行,结果为 12 行)。这会导致数据冗余且无意义,因此多表查询必须通过关联条件(通常是whereon子句)消除笛卡尔积。

二、代码详细讲解

1. 创建user表及操作
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 '用户表';
  • 作用:创建名为user的用户表。
  • 字段说明
    • id:整数类型,主键(primary key),自增(auto_increment),唯一标识每条记录。
    • name:长度 10 的字符串,非空(not null)且唯一(unique),确保姓名不重复。
    • age:整数,通过check约束限制年龄在 0-120 之间(注意:MySQL 8.0.16 + 才真正支持check约束,低版本仅语法校验不生效)。
    • status:长度 1 的字符,默认值为 '1'(如可表示 “启用” 状态)。
    • gender:长度 1 的字符,存储性别(如 ' 男'/' 女 ')。
select * from user;
  • 作用:查询user表中所有字段的所有记录(初始为空,后续插入数据后可见结果)。
insert into user(name, age, status, gender) values 
('Tom1', 19, '0', '男'),
('Tom2', 25, '1', '女'),
('Tom3', 17, '0', '男');
  • 作用:向user表插入 3 条记录,指定nameagestatusgender字段的值。
  • 注意id是自增主键,无需手动插入,会自动生成 1、2、3。
insert into user(name, age, gender) values ('Tom5', 32,'男');
  • 作用:向user表插入第 4 条记录,仅指定nameagegender
  • 注意status字段未指定,将使用默认值 '1'(定义表时设置的default '1')。
2. 创建dept表及操作
create table dept(id int primary key auto_increment comment 'ID' ,name varchar(50) not null comment '部门名称'
)comment '部门表';
  • 作用:创建名为dept的部门表,存储部门信息。
  • 字段说明
    • id:自增主键,部门唯一标识。
    • name:部门名称,非空(确保每个部门有名称)。
insert into dept values (1, '研发部'),(2,'市场部'),(3, '财务部'),(4, '销售部'),(5, '总经办');
  • 作用:插入 5 条部门记录,手动指定id(1-5)和对应部门名称。
  • 注意:虽然id是自增主键,但此处手动插入值后,后续自增会从 6 开始。
select * from dept;
  • 作用:查询dept表所有记录,验证插入的部门数据。
3. 创建emp表及操作
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 '入职时间',managerid int comment '直属领导ID',dept_id int comment '部门ID'
)comment '员工表';
  • 作用:创建名为emp的员工表,存储员工信息。
  • 字段说明
    • managerid:关联自身表的id(表示员工的直属领导)。
    • dept_id:关联dept表的id(表示员工所属部门)。
insert into emp values 
(1, '金庸', 66, '总裁', 20000, '2000-01-01', null, 5),
(2, '张无忌', 20, '项目经理', 12500, '2005-12-01', 1, 1),
(3, '杨晓', 33, '开发', 8400, '2003-01-01', 2, 1),
(4, '韦一笑', 66, '开发', 11000, '2002-02-02', 2, 1),
(5, '常遇春', 43, '开发', 10500, '2004-09-05', 3, 1),
(6, '小昭', 19, '文员', 6000, '2004-10-14', 2, 1);
  • 作用:插入 6 条员工记录,包含姓名、年龄、职位等信息。
  • 说明
    • manageridnull表示 “金庸” 没有上级(总裁)。
    • dept_id对应dept表的id(如dept_id=1表示属于 “研发部”)。
4. 外键约束操作
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);
  • 作用:给emp表的dept_id添加外键约束,关联dept表的id
  • 说明
    • 外键约束确保emp.dept_id的值必须是dept.id中已存在的值(或null),防止无效的部门关联。
    • fk_emp_dept_id是约束的名称(自定义,便于后续操作)。
alter table emp drop foreign key fk_emp_dept_id;
  • 作用:删除emp表中名为fk_emp_dept_id的外键约束。
  • 注意:删除外键后,emp.dept_id可以插入dept.id中不存在的值(可能导致数据不一致,需谨慎)。
select * from emp;
  • 作用:查询emp表所有记录,验证员工数据。
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on UPDATE cascade on DELETE cascade ;
  • 作用:重新添加外键约束,并设置级联更新和级联删除。
  • 说明
    • on update cascade:当dept.id更新时,emp.dept_id自动同步更新。
    • on delete cascade:当dept表中某部门被删除时,emp表中关联该部门的记录也会被删除。
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update set null on delete set null ;
  • 作用:修改外键约束为 “级联设空”。
  • 说明
    • on update set null:当dept.id更新时,emp.dept_id被设为null
    • on delete set null:当dept表中某部门被删除时,emp表中关联该部门的dept_id被设为null
5. 多表查询操作
select * from emp, dept where emp.dept_id = dept.id;
  • 作用:查询empdept表的关联数据,通过where条件消除笛卡尔积。
  • 说明
    • 若不加where emp.dept_id = dept.id,会产生笛卡尔积(emp6 行 × dept5 行 = 30 行无效数据)。
    • 加条件后,只保留emp.dept_iddept.id匹配的记录(即员工所属部门存在的记录)。
-- 隐式内连接
select emp.name, dept.name from emp, dept where emp.dept_id = dept.id;
  • 作用:隐式内连接查询,只获取两表交集(员工和其所属部门均存在的记录)。
  • 说明
    • 隐式内连接用逗号分隔表,通过where指定关联条件。
    • 只查询emp.name(员工姓名)和dept.name(部门名称),避免返回冗余字段。
-- 显式内连接
select emp.name, dept.name from emp inner join dept on emp.dept_id = dept.id;
  • 作用:显式内连接查询,功能与隐式内连接一致(查询两表交集)。
  • 说明
    • 显式内连接用inner join关键字,关联条件用on子句(推荐,更清晰)。
    • inner可省略,即select ... from emp join dept on ...
-- 左外连接
select emp.*, d.name from emp left outer join dept d on emp.dept_id = d.id;
  • 作用:左外连接查询,返回左表(emp)所有记录,以及右表(dept)中匹配的记录(右表无匹配则显示null)。
  • 说明
    • left outer joinouter可省略,简写为left join
    • dept ddept表起别名d,简化查询语句。
    • 即使某员工的dept_idnull(无部门),也会被查询出来。
-- 右外连接
select d.name,emp.* from emp right join dept d on emp.dept_id = d.id;
  • 作用:右外连接查询,返回右表(dept)所有记录,以及左表(emp)中匹配的记录(左表无匹配则显示null)。
  • 说明
    • 例如dept表中有 “市场部”(id=2),但emp表中无该部门员工,则结果中 “市场部” 对应的员工字段为null
    • 右外连接可通过交换表位置转为左外连接(如dept left join emp on ...)。
-- 自连接(查询员工及其领导姓名)
select 员工表.name, 领导表.name from emp 员工表, emp 领导表 where 员工表.managerid = 领导表.id;
  • 作用:自连接查询(表与自身连接),获取员工及其直属领导的姓名。
  • 说明
    • 需给表起别名(员工表领导表)区分同一表的不同角色。
    • 关联条件员工表.managerid = 领导表.id:员工的领导 ID 对应另一员工的 ID。
    • 结果中不会包含 “金庸”(因manageridnull,无领导)。
-- 自连接(包含无领导的员工)
select 员工表.name, 领导表.name from emp 员工表 left join emp 领导表 on 员工表.managerid = 领导表.id;
  • 作用:左外自连接,查询所有员工及其领导姓名(包括无领导的员工)。
  • 说明
    • “金庸” 的manageridnull,左连接会保留该记录,领导表.name显示null

三、关键注意事项

  1. 外键约束:关联字段类型必须一致(如emp.dept_iddept.id均为int);外键可设为null(表示无关联)。
  2. 笛卡尔积:多表查询必须加关联条件(whereon),否则结果无意义。
  3. 连接类型:内连接只取交集,外连接保留主表所有记录,自连接用于表内层级关系(如员工 - 领导)。
  4. 表别名:多表查询(尤其是自连接)需用别名简化语句,避免字段歧义(如emp.name vs dept.name)。
http://www.dtcms.com/a/395212.html

相关文章:

  • Hive SQL 中的时间戳转换详解
  • Linux笔记---select、poll、epoll总结对比
  • MySQL查询详细介绍
  • 面试题二:业务篇
  • Rust进阶-part8-迭代器
  • halcon3d gen_image_to_world_plan3_map与project_3d_point
  • Ellisys工具
  • Qwen3-7B-Instruct Windows LMStudio 部署
  • 【代码】关于C#支持文件和文本框的简单日志实现
  • atcoder经典好题
  • 【Linux】Linux文件系统详解:从磁盘到文件的奥秘
  • 【Android Keystore】Android 密钥库系统使用指南
  • RBAC权限模型实战图解:绘制企业权限矩阵,告别混乱授权
  • 【ROS2】通讯协议接口 Interface
  • Spring —— 事务控制
  • 基于vue开发的背单词网站
  • javascript 角色跟踪实践
  • 第九周作业
  • 【ThinkPHP项目添加新页面完整解决方案】
  • Thinkphp框架相关漏洞扫描器(一)
  • 【网络通讯】Qt中使用Modbus Tcp协议(附Demo)
  • 在 macOS 上使用 Windows 快捷键指南
  • pd26 虚拟机 (Mac中文)
  • 本周的股指
  • (论文速读)生成式摄影:让AI理解相机的物理世界
  • ELK 企业级日志分析系统
  • 项目日记 -日志系统 -功能完善
  • install_docker.sh
  • opencv的DNN模块里
  • FPGA学习笔记——图像处理之对比度调节(线性调节)