MySQL 进阶篇 —— 事务 / 外键 / 索引 / 高级查询

MySQL 进阶内容,涵盖事务、主外键、索引及高级查询技巧


一、事务(TCL)

1.1 什么是事务

一组 SQL 操作的逻辑单元,要么全部成功,要么全部失败

1.2 ACID 特性

特性 说明
原子性 所有操作全部成功或全部失败
一致性 事务前后数据完整性一致
隔离性 多个事务并发互不影响
持久性 事务提交后永久保存

1.3 事务操作语句

语句 作用
begin 开始事务
commit 提交事务(永久保存)
rollback 回滚事务(撤销全部操作)
savepoint 名称 设置保存点
rollback to 名称 回滚到指定保存点

多个窗口可多事务并发,但单窗口只能有一个事务。事务结束标志是 rollbackcommit。下一个事务开启会隐式提交上一个事务。

1.4 事务示例

sql 复制代码
-- 前提:只有 InnoDB 引擎支持事务
create table accounts (
    id int unsigned primary key auto_increment,
    name varchar(20),
    balance decimal(10,2)
) engine=InnoDB default charset=utf8mb4;

insert into accounts values (1, '张三', 1000), (2, '李四', 0);

-- 正常提交
begin;
update accounts set balance = balance - 500 where id = 1;
update accounts set balance = balance + 500 where id = 2;
commit;

-- 回滚撤销
begin;
update accounts set balance = balance - 200 where id = 1;
update accounts set balance = balance + 200 where id = 2;
rollback;

-- 保存点回滚
begin;
update accounts set balance = 500 where id = 1;
savepoint sp1;
update accounts set balance = 500 where id = 2;
rollback to sp1;
commit;

二、主键与外键

2.1 主键(primary key)

特点 说明
字段值必须唯一 不允许重复
字段值不可为空 not null
一张表仅一个主键 可单字段或组合字段
自动生成唯一索引 创建主键时自动附带

2.2 外键(foreign key)

引用另一张表的主键,用于建立表间关联。

特点 说明
字段值可以不唯一 允许重复
字段值可以为空 允许 null
一张表可有多个外键
自动生成普通索引 创建外键时自动附带

2.3 创建外键失败常见原因

  • 关联的两个字段数据类型不匹配
  • 子表已有存量数据违反外键约束
  • 被引用的主表主键缺少配套索引

2.4 级联规则(on delete / on update)

规则 行为
on delete cascade 主表删除,子表关联数据同步删除
on delete set null 主表删除,子表外键置 null(需允许 null)
默认(不写规则) 子表有关联数据时,禁止删除主表
sql 复制代码
-- 主表
create table products_2 (
    pid int unsigned primary key auto_increment,
    pname varchar(40),
    price decimal(10,2)
);

-- 子表:级联删除
create table orders_2 (
    oid int unsigned primary key auto_increment,
    pid int unsigned,
    buy_num int,
    foreign key fk_pid(pid) references products_2(pid)
    on delete cascade on update cascade
);

-- 子表:置空处理(pid 必须允许 null)
create table orders_3 (
    oid int unsigned primary key auto_increment,
    pid int unsigned null,
    buy_num int,
    foreign key fk_pid2(pid) references products_2(pid)
    on delete set null
);

三、索引

3.1 什么是索引

类似书籍目录,作用是加快数据查询速度

有索引 无索引
直接定位数据,类似查目录 逐行全表扫描
查询效率大幅提升 数据量大时极慢

3.2 优缺点

优点 缺点
大幅提高查询速度 占用额外磁盘空间
减少磁盘 IO 增删改需同步维护索引,降低写入性能
避免全表扫描 数据越大,索引占用越多

3.3 存储结构分类

类型 适用场景
B+ 树索引 范围查询、in 查询(默认)
哈希索引 仅支持精准等值 = 查询
全文索引 文本模糊 like 检索

3.4 功能分类

类型 特点 语法
普通索引 允许重复、允许 null create index idx_name on 表(字段);
唯一索引 值必须唯一、允许 null create unique index idx_name on 表(字段);
主键索引 唯一 + 非空,一张表仅一个 创建主键自动生成
组合索引 多字段联合 create index idx_a_b on 表(字段1,字段2);
全文索引 长文本检索 create fulltext index idx_text on 表(字段);
sql 复制代码
-- 创建普通索引
create index idx_pname on products(pname);

-- 创建唯一索引
create unique index idx_price on products(price);

-- 创建组合索引
create index idx_name_stock on products(name, stock);

-- 查看索引
show index from products;
show create table products;

-- 删除索引
drop index idx_pname on products;

MySQL 不支持直接修改索引,需要先删除旧索引再重新创建新索引。


四、高级 DQL

4.1 条件判断(case when)

类似编程中的 if-else,根据条件生成新列:

sql 复制代码
select
    name, price,
    case
        when price < 500 then '低价'
        when price between 500 and 3000 then '中价'
        else '高价'
    end as '价格等级'
from products;

4.2 空值处理(ifnull)

sql 复制代码
select ifnull(name, '无名商品') as '商品名称', price from products;

4.3 字符串函数

sql 复制代码
select concat(name, ' - ', city) as '顾客信息' from customers;
select name, char_length(name) as '名称长度' from products;

4.4 分页查询(limit offset)

sql 复制代码
-- limit 每页条数 offset 跳过条数
select * from products order by price desc limit 3 offset 0;  -- 第 1 页
select * from products order by price desc limit 3 offset 3;  -- 第 2 页

4.5 exists

sql 复制代码
-- 有下过单的顾客
select * from customers as c
where exists (
    select 1 from orders as o where o.customer_id = c.id
);

-- 从未被购买过的商品
select * from products as p
where not exists (
    select 1 from order_items as oi where oi.product_id = p.id
);

4.6 union 合并结果集

sql 复制代码
select name as '名称' from customers
union
select name as '名称' from products;

-- union all 保留重复(更快)
select name as '名称' from customers
union all
select name as '名称' from products;

4.7 窗口函数(window function)

在不改变行数的情况下对分组内数据排序、排名、累计:

sql 复制代码
-- row_number:为每行赋予唯一连续排名
select
    name, price,
    row_number() over (order by price desc) as '价格排名'
from products;

-- rank:相同值并列排名,会跳过后续序号(如 1,1,3)
select
    name, price,
    rank() over (order by price desc) as '价格排名'
from products;

-- dense_rank:相同值并列排名,不跳过后续序号(如 1,1,2)
select
    name, price,
    dense_rank() over (order by price desc) as '价格排名'
from products;

五、总结

分类 核心操作 关键字/语法
事务 开启/提交/回滚 begin / commit / rollback / savepoint
事务 ACID 原子性、一致性、隔离性、持久性
外键 级联删除 on delete cascade
外键 置空处理 on delete set null
索引 普通/唯一/组合/全文 create index / create unique index / create fulltext index
索引 查看/删除 show index from / drop index
高级 DQL 条件判断 case when ... then ... else ... end
高级 DQL 空值处理 ifnull()
高级 DQL 字符串函数 concat() / char_length()
高级 DQL 分页 limit ... offset ...
高级 DQL exists exists / not exists
高级 DQL 合并结果集 union / union all
高级 DQL 窗口函数 row_number() / rank() / dense_rank() / over
相关推荐
爬也要爬着前进8 小时前
redis哨兵模式搭建
数据库·redis·bootstrap
小月土星8 小时前
(实战篇)RAG-demo 深度解析:162行代码中的检索增强生成全景 (含Top-k法)
javascript·数据库·llm
晴雨天️9 小时前
Git工具使用指南
笔记·git
醉城夜风~9 小时前
MyBatis 基础CRUD全套实战学习笔记
笔记·学习·mybatis
Csvn9 小时前
📊 SQL 入门 Day 5:GROUP BY & HAVING — 开始分组分析
后端·sql
Flandern11119 小时前
从“能跑”到“可运营”:Agent Harness 工程化建设指南
学习·agent·claudecode·harness
hj2862519 小时前
Shell 脚本完整学习笔记
chrome·笔记·学习
m0_377108149 小时前
cmake学习
学习
智者知已应修善业9 小时前
【proteus交通灯故障检测的完善方案】2025-4-29
经验分享·笔记·单片机·嵌入式硬件·proteus