MySQL多表查询和事务

在实际的数据库应用中,数据通常分布在多个相关的表中,如何高效地从这些表中获取和处理数据是数据库开发中的重要课题。多表查询提供了强大的数据检索能力,通过连接查询和子查询,我们可以灵活地组合和筛选来自不同表的数据。同时,在进行数据修改操作时,事务管理机制确保了数据的一致性和完整性,是构建可靠数据库应用的基石。

本文将系统地介绍MySQL中的多表查询和事务管理。首先从多表查询的基本概念入手,详细讲解内连接、外连接等不同的连接查询方式,以及子查询的多种使用场景。接着深入探讨事务的概念、特性和隔离级别,帮助读者理解如何在实际开发中正确使用事务来保证数据的安全性。文章配有丰富的示例代码,便于读者实践和掌握这些重要的数据库操作技术。

建议读者在学习本文时,结合实际案例进行练习,特别是在理解不同类型的连接查询和事务隔离级别时,动手实践是加深理解的最好方式。

一、多表查询基础

1.1 概念

多表查询是指从多个表中获取数据的查询操作。在进行多表查询时会产生笛卡尔积,即两个集合的所有组合情况。为了得到有意义的查询结果,需要通过条件消除无用的数据。

1.2 基本语法

sql 复制代码
SELECT 列名列表
FROM 表名列表
WHERE 条件;

1.3 示例数据准备

sql 复制代码
-- 部门表
CREATE TABLE dept(
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(20)
);

-- 插入部门数据
INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');

-- 员工表
CREATE TABLE emp (
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(10),
  gender CHAR(1), -- 性别
  salary DOUBLE, -- 工资
  join_date DATE, -- 入职日期
  dept_id INT,
  FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键)
);

-- 插入员工数据
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES
('孙悟空','男',7200,'2013-02-24',1),
('猪八戒','男',3600,'2010-12-02',2),
('唐僧','男',9000,'2008-08-08',2),
('白骨精','女',5000,'2015-10-07',3),
('蜘蛛精','女',4500,'2011-03-14',1);

二、连接查询

2.1 内连接查询

2.1.1 隐式内连接

使用WHERE条件消除无用数据

sql 复制代码
-- 查询所有员工信息和对应的部门信息
SELECT * FROM emp,dept 
WHERE emp.dept_id = dept.id;

-- 使用别名优化查询(推荐)
SELECT
    t1.name AS '姓名', 
    t1.gender AS '性别',
    t2.name AS '部门'
FROM
    emp t1,
    dept t2
WHERE
    t1.dept_id = t2.id;

2.1.2 显式内连接

使用INNER JOIN关键字,语法更直观

sql 复制代码
-- 标准语法
SELECT * FROM emp
INNER JOIN dept ON emp.dept_id = dept.id;

-- INNER可以省略
SELECT * FROM emp
JOIN dept ON emp.dept_id = dept.id;

2.2 外连接查询

2.2.1 左外连接

查询左表所有数据以及其与右表的交集部分

sql 复制代码
-- 查询所有员工信息及其部门信息(包括没有部门的员工)
SELECT t1.*, t2.name AS '部门名称'
FROM emp t1 
LEFT JOIN dept t2 
ON t1.dept_id = t2.id;

2.2.2 右外连接

查询右表所有数据以及其与左表的交集部分

sql 复制代码
-- 查询所有部门信息及其员工信息(包括没有员工的部门)
SELECT t1.*, t2.name AS '员工姓名'
FROM dept t1 
RIGHT JOIN emp t2 
ON t2.dept_id = t1.id;

三、子查询

3.1 概念

子查询是指查询中嵌套查询,内部的查询称为子查询。

3.2 子查询分类

3.2.1 单行单列子查询

子查询结果为单个值,可以使用比较运算符

sql 复制代码
-- 查询工资最高的员工信息
SELECT * FROM emp 
WHERE salary = (SELECT MAX(salary) FROM emp);

-- 查询工资小于平均工资的员工
SELECT * FROM emp 
WHERE salary < (SELECT AVG(salary) FROM emp);

3.2.2 多行单列子查询

子查询结果为一列多行,可以使用IN等运算符

sql 复制代码
-- 查询财务部和市场部的所有员工信息
SELECT * FROM emp 
WHERE dept_id IN (
    SELECT id FROM dept 
    WHERE NAME IN ('财务部','市场部')
);

3.2.3 多行多列子查询

子查询结果可以作为一张虚拟表

sql 复制代码
-- 查询2011-11-11后入职的员工信息和部门信息
SELECT * FROM dept t1,
(SELECT * FROM emp WHERE join_date > '2011-11-11') t2
WHERE t1.id = t2.dept_id;

四、事务管理

4.1 事务概念

事务是一组操作的集合,这些操作要么全部成功,要么全部失败。事务是数据库维护数据一致性的单位。

4.2 事务的基本操作

sql 复制代码
-- 开启事务
START TRANSACTION;

-- 提交事务
COMMIT;

-- 回滚事务
ROLLBACK;

4.3 事务示例

sql 复制代码
-- 创建账户表
CREATE TABLE account (
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(10),
  balance DOUBLE
);

-- 添加测试数据
INSERT INTO account (NAME, balance) 
VALUES ('张三', 1000), ('李四', 1000);

-- 转账操作
START TRANSACTION;
-- 张三账户减500
UPDATE account SET balance = balance - 500 
WHERE NAME = '张三';
-- 李四账户加500
UPDATE account SET balance = balance + 500 
WHERE NAME = '李四';
COMMIT;

4.4 事务的四大特性(ACID)

  1. 原子性(Atomicity):事务是不可分割的最小操作单位
  2. 一致性(Consistency):事务执行前后,数据保持一致
  3. 隔离性(Isolation):多个事务之间相互独立
  4. 持久性(Durability):事务一旦提交,结果永久保存

4.5 事务的隔离级别

隔离级别 脏读 不可重复读 幻读 描述
READ UNCOMMITTED 读未提交
READ COMMITTED 读已提交(Oracle默认)
REPEATABLE READ 可重复读(MySQL默认)
SERIALIZABLE 串行化
sql 复制代码
-- 查询当前隔离级别
SELECT @@tx_isolation;

-- 设置隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

注意:隔离级别从低到高安全性越来越高,但性能越来越低。应根据实际业务需求选择合适的隔离级别。

相关推荐
Seven975 分钟前
【设计模式】通过访问者模式实现分离算法与对象结构
java·后端·设计模式
Seven9723 分钟前
【设计模式】遍历集合的艺术:深入探索迭代器模式的无限可能
java·后端·设计模式
小杨40428 分钟前
springboot框架项目应用实践五(websocket实践)
spring boot·后端·websocket
浪九天29 分钟前
Java直通车系列28【Spring Boot】(数据访问Spring Data JPA)
java·开发语言·spring boot·后端·spring
dengjiayue42 分钟前
golang 高性能的 MySQL 数据导出
开发语言·mysql·golang
bobz9651 小时前
IKEv1 和 IKEv2 发展历史和演进背景
后端
大鹏dapeng1 小时前
Gone v2 goner/gin——试试用依赖注入的方式打开gin-gonic/gin
后端·go
熙曦Sakura2 小时前
【MySQL】数据类型
android·mysql·adb
tan180°2 小时前
版本控制器Git(1)
c++·git·后端
GoGeekBaird2 小时前
69天探索操作系统-第50天:虚拟内存管理系统
后端·操作系统