MySQL 核心高级特性

一、主键(Primary Key):表的 "唯一身份证"

主键是表中用于唯一标识每条记录的字段(或字段组合),是关系型数据库数据完整性的基础。

1. 核心特性

  • 唯一性:主键值不可重复,确保每条记录都能被唯一识别。
  • 非空性 :主键字段自动默认 NOT NULL,不允许空值。
  • 单一性:一个表只能有一个主键(可由多列组合,即 "复合主键")。
  • 索引自带:主键会自动创建聚簇索引,大幅提升查询效率。

2. 主要作用

  • 数据标识 :在全表或跨表场景中,精准定位某一条记录(如用户表用 id 唯一标识用户)。
  • 完整性维护 :阻止重复或无效数据插入 / 更新(如避免用户表出现两个相同 id 的记录)。
  • 提升查询性能:基于主键的查询会通过聚簇索引快速定位,避免全表扫描。
  • 表间关联基础 :作为外键的引用源,实现多表关联(如订单表的 user_id 引用用户表的 id)。

3. 实战操作

创建主键(建表时)
复制代码
-- 单字段主键(最常用)
CREATE TABLE users (
    id INT AUTO_INCREMENT,  -- 自增属性常与主键搭配
    username VARCHAR(50) NOT NULL,
    password VARCHAR(50) NOT NULL,
    PRIMARY KEY (id)  -- 声明 id 为主键
);

-- 复合主键(多字段组合,如"学生-课程"关联表)
CREATE TABLE student_course (
    student_id INT NOT NULL,
    course_id INT NOT NULL,
    score INT,
    PRIMARY KEY (student_id, course_id)  -- 两字段组合为主键
);
修改主键

MySQL 不支持直接修改主键,需先删除旧主键,再创建新主键:

复制代码
-- 1. 删除旧主键
ALTER TABLE users DROP PRIMARY KEY;
-- 2. 创建新主键(如将 username 设为主键,需确保其唯一非空)
ALTER TABLE users ADD PRIMARY KEY (username);
删除主键
复制代码
ALTER TABLE users DROP PRIMARY KEY;

二、外键(Foreign Key):表间的 "关联桥梁"

外键是用于关联两个表的字段,确保子表(从表)的记录在父表(主表)中存在对应值,维护多表数据一致性。

1. 核心特性

  • 参照完整性 :子表外键值必须是父表主键(或唯一键)的已存在值(或 NULL,若外键允许空)。
  • 级联操作支持:可配置 "级联更新""级联删除",父表数据变更时自动同步子表。
  • 依赖主键:外键必须引用父表的主键或唯一键(确保引用字段值唯一)。

2. 主要作用

  • 防止孤立数据 :避免子表出现 "无父记录" 的数据(如订单表的 user_id 不能指向不存在的用户)。
  • 简化多表操作:通过外键实现多表连接查询(如关联用户表和订单表,查询某用户的所有订单)。
  • 规范数据模型:清晰表达表间关系(如 "用户 - 订单" 的一对多关系),减少数据冗余。

3. 实战操作

创建外键(建表时)
复制代码
-- 父表:users(已存在,主键为 id)
-- 子表:orders(通过 user_id 关联 users 的 id)
CREATE TABLE orders (
    order_id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,  -- 外键字段
    owner VARCHAR(50) NOT NULL,
    level INT NOT NULL,
    -- 声明外键:user_id 引用 users 的 id
    FOREIGN KEY (user_id) REFERENCES users(id)
        -- 可选:级联操作配置
        ON UPDATE CASCADE  -- 父表 id 更新时,子表 user_id 自动同步
        ON DELETE SET NULL  -- 父表记录删除时,子表 user_id 设为 NULL(需外键允许空)
);
修改外键

需先删除旧外键,再创建新外键(外键需命名,便于删除):

复制代码
-- 1. 查看外键名(若未自定义,MySQL 会自动生成)
SHOW CREATE TABLE orders;  -- 输出中找"CONSTRAINT 外键名 FOREIGN KEY..."
-- 2. 删除旧外键(假设外键名为 fk_orders_user)
ALTER TABLE orders DROP FOREIGN KEY fk_orders_user;
-- 3. 创建新外键(如关联新的父表 new_users 的 id)
ALTER TABLE orders ADD CONSTRAINT fk_orders_newuser
    FOREIGN KEY (user_id) REFERENCES new_users(id);
删除外键
复制代码
ALTER TABLE orders DROP FOREIGN KEY fk_orders_user;

三、索引(Index):查询的 "加速引擎"

索引是对表中一个或多个字段的值进行排序的特殊数据结构,核心作用是减少数据扫描范围,提升查询速度。

1. 核心特性

  • 加速查询:通过索引快速定位数据,避免全表扫描(尤其大数据量场景)。
  • 不改变数据:索引是 "数据的副本",不影响表中原始数据的存储。
  • 有维护成本:插入 / 更新 / 删除数据时,需同步更新索引,可能降低写操作性能。

2. 索引分类(按常用维度)

分类维度 类型 特点与应用场景
数据结构 B+Tree 索引 支持范围查询、排序,MySQL 默认索引类型(如主键索引、普通索引)
Hash 索引 仅支持等值查询,速度极快,Memory 引擎支持(如用户登录时按用户名查密码)
Fulltext 索引 支持文本分词搜索,适用于文章、商品描述等长文本字段(如博客内容关键词查询)
物理存储 聚簇索引 索引与数据存储在一起,表仅一个(通常是主键),范围查询效率高
二级索引(辅助索引) 索引存储聚簇索引值,需 "回表" 查询数据(如普通索引、前缀索引)
字段个数 单列索引 仅对单个字段建索引(如按 age 查学生)
联合索引(复合索引) 对多个字段建索引,需遵循 "最左前缀原则"(如按 customer_id+order_date 查订单)

3. 实战操作

创建索引
复制代码
-- 1. 普通索引(单列,B+Tree 类型)
CREATE INDEX idx_users_username ON users(username);

-- 2. 联合索引(多列,需注意字段顺序)
CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);

-- 3. 前缀索引(对长字段前 N 个字符建索引,减少存储)
CREATE INDEX idx_url_prefix ON urls(url(10));  -- 对 url 前 10 个字符建索引

-- 4. Fulltext 索引(文本搜索)
CREATE FULLTEXT INDEX idx_articles_content ON articles(content);
查看索引
复制代码
-- 查看表的所有索引
SHOW INDEX FROM users;
-- 或通过信息_schema 查看
SELECT * FROM information_schema.STATISTICS WHERE TABLE_NAME = 'users';
修改索引

MySQL 不支持直接修改索引,需先删除再重建:

复制代码
-- 1. 删除旧索引
DROP INDEX idx_users_username ON users;
-- 2. 创建新索引(如将前缀长度改为 15)
CREATE INDEX idx_users_username ON users(username(15));
删除索引
复制代码
DROP INDEX idx_users_username ON users;
强制使用索引

当 MySQL 优化器选择错误索引时,可强制指定索引:

复制代码
SELECT * FROM users FORCE INDEX (idx_users_username) WHERE username = 'tom';
索引使用追踪(EXPLAIN)

通过 EXPLAIN 分析索引是否被使用:

复制代码
EXPLAIN SELECT * FROM users WHERE username = 'tom';

关键字段解读:

  • type:访问类型(const 最佳,ALL 为全表扫描,需优化);
  • key:实际使用的索引(NULL 表示未用索引);
  • rows:估算扫描行数(越少越好)。

四、Check 约束(Check Constraint):数据的 "合法性门卫"

Check 约束用于强制字段值满足特定条件,确保插入 / 更新的数据符合业务规则(MySQL 8.0.16 及以后正式支持)。

1. 核心特性

  • 条件验证:仅允许满足约束条件的数据写入(如年龄必须在 18-60 岁)。
  • 数据库层控制:无需在应用层重复写验证逻辑,确保多端操作的数据一致性。
  • 支持复杂条件:可基于单个字段或多字段组合设置条件(如订单最终金额 = 总金额 × (1 - 折扣率))。

2. 主要作用

  • 数据有效性:防止非法数据(如负金额、无效日期)写入数据库。
  • 简化应用逻辑:减少应用层代码冗余(如无需在后端、前端分别写年龄验证)。
  • 维护数据质量:与主键、外键配合,构建完整的数据完整性体系。

3. 实战操作

创建 Check 约束
复制代码
-- 1. 建表时添加(单字段条件)
CREATE TABLE employees (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT CHECK (age >= 18 AND age <= 60),  -- 年龄约束 18-60 岁
    salary DECIMAL(10,2) CHECK (salary > 0)   -- 薪资约束为正数
);

-- 2. 建表后添加(多字段条件,需命名约束)
ALTER TABLE orders ADD CONSTRAINT chk_orders_finalamount
    CHECK (final_amount = total_amount * (1 - discount_rate));
查看 Check 约束
复制代码
-- 通过 information_schema 查看表的所有约束
SELECT * FROM information_schema.TABLE_CONSTRAINTS 
WHERE TABLE_NAME = 'employees' AND CONSTRAINT_TYPE = 'CHECK';
修改 Check 约束

需先删除旧约束,再创建新约束:

复制代码
-- 1. 删除旧约束(假设约束名为 chk_employees_age)
ALTER TABLE employees DROP CONSTRAINT chk_employees_age;
-- 2. 创建新约束(如年龄改为 20-65 岁)
ALTER TABLE employees ADD CONSTRAINT chk_employees_age
    CHECK (age >= 20 AND age <= 65);
删除 Check 约束
复制代码
ALTER TABLE employees DROP CONSTRAINT chk_employees_age;

4. 使用注意事项

  • 性能影响:复杂约束(如多字段运算)会增加插入 / 更新的耗时,避免过度使用。
  • 兼容性:低版本 MySQL(<8.0.16)会忽略 Check 约束,需用触发器替代。
  • 合理性:约束条件需符合业务逻辑(如不要设置 "年龄必须为偶数" 这类无意义约束)。

五、存储过程(Stored Procedure):SQL 代码的 "封装容器"

存储过程是预先编译并存储在数据库中的一组 SQL 语句集合,可通过调用名执行,实现业务逻辑封装。

1. 核心特性

  • 预编译:创建时编译,调用时无需重复编译,提升执行效率。
  • 封装性:将复杂逻辑(如多表更新、数据统计)封装为一个单元,便于复用。
  • 支持参数:可接收输入(IN)、输出(OUT)参数,灵活传递数据(如传入用户 ID,返回用户信息)。

2. 核心优点

  • 提升性能:减少 SQL 语句网络传输量(仅传调用名和参数),尤其适合复杂逻辑。
  • 增强安全性:用户可调用存储过程,但不能直接操作表,防止误删 / 篡改数据。
  • 简化维护:业务逻辑变更时,仅需修改存储过程,无需修改所有调用它的应用。

3. 实战操作

创建存储过程
复制代码
-- 示例:根据用户 ID 查询用户信息(带输入参数)
DELIMITER //  -- 修改语句结束符为 //(避免与存储过程内 ; 冲突)
CREATE PROCEDURE sp_get_user_info(IN user_id INT)  -- IN 表示输入参数
BEGIN
    SELECT id, username, password FROM users WHERE id = user_id;
END //
DELIMITER ;  -- 恢复结束符为 ;

-- 示例:统计订单总数(带输出参数)
DELIMITER //
CREATE PROCEDURE sp_count_orders(OUT total INT)  -- OUT 表示输出参数
BEGIN
    SELECT COUNT(*) INTO total FROM orders;  -- 将结果存入输出参数
END //
DELIMITER ;
查看存储过程
复制代码
-- 1. 查看所有存储过程
SHOW PROCEDURE STATUS\G;

-- 2. 查看指定数据库的存储过程(如 bank 库)
SHOW PROCEDURE STATUS WHERE Db = 'bank'\G;

-- 3. 查看存储过程的创建语句
SHOW CREATE PROCEDURE sp_get_user_info\G;
调用存储过程
复制代码
-- 1. 调用带输入参数的存储过程
CALL sp_get_user_info(1001);

-- 2. 调用带输出参数的存储过程(需先声明变量接收结果)
SET @order_total = 0;
CALL sp_count_orders(@order_total);
SELECT @order_total AS 订单总数;
修改与删除存储过程
复制代码
-- 修改:需先删除再重建
DROP PROCEDURE IF EXISTS sp_get_user_info;
-- 重建新逻辑...

-- 删除存储过程
DROP PROCEDURE IF EXISTS sp_get_user_info;

六、触发器(Trigger):表操作的 "自动响应器"

触发器是与表关联的特殊存储过程,当表发生 INSERT/UPDATE/DELETE 操作时,自动执行预设逻辑。

1. 核心特性

  • 自动触发:无需手动调用,触发事件发生时自动执行。
  • 与表绑定:触发器属于某张表,表删除时触发器也随之删除。
  • 支持新旧数据 :通过 NEW(新数据)、OLD(旧数据)关键字访问操作前后的数据。

2. 触发器类型(按触发时机与事件)

触发时机 触发事件 作用示例
BEFORE INSERT 插入前修改数据(如给用户名自动加前缀)、验证数据合法性
AFTER INSERT 插入后同步数据(如插入订单后,更新商品库存)
BEFORE UPDATE 更新前校验新值(如薪资不能低于旧值)
AFTER UPDATE 更新后记录日志(如记录用户密码修改时间)
BEFORE DELETE 删除前备份数据(如删除用户前,将数据备份到历史表)
AFTER DELETE 删除后清理关联数据(如删除用户后,删除其所有订单)

3. 实战操作

创建触发器
复制代码
-- 示例 1:INSERT 前自动设置订单日期
DELIMITER //
CREATE TRIGGER trg_orders_set_date BEFORE INSERT ON orders
FOR EACH ROW  -- 行级触发器,每插入一行执行一次
BEGIN
    SET NEW.order_date = CURDATE();  -- NEW 表示待插入的新行
END //
DELIMITER ;

-- 示例 2:DELETE 后自动删除关联的用户记录
DELIMITER //
CREATE TRIGGER trg_orders_delete_user AFTER DELETE ON orders
FOR EACH ROW
BEGIN
    DELETE FROM users WHERE id = OLD.user_id;  -- OLD 表示待删除的旧行
END //
DELIMITER ;
查看触发器
复制代码
-- 查看所有触发器(\G 格式化输出,便于阅读)
SHOW TRIGGERS\G;

-- 查看指定表的触发器
SELECT * FROM information_schema.TRIGGERS WHERE TABLE_NAME = 'orders';
修改与删除触发器
复制代码
-- 修改:需先删除再重建
DROP TRIGGER IF EXISTS trg_orders_set_date;
-- 重建新逻辑...

-- 删除触发器
DROP TRIGGER trg_orders_set_date;

4. 关键概念:NEWOLD

  • NEW:仅用于 INSERT/UPDATE,表示操作后的数据(INSERT 时是新插入的行,UPDATE 时是更新后的行)。
  • OLD:仅用于 UPDATE/DELETE,表示操作前的数据(UPDATE 时是更新前的行,DELETE 时是待删除的行)。

七、事务(Transaction):数据操作的 "原子保证"

事务是一组不可分割的 SQL 操作集合,要么全部执行成功(提交),要么全部执行失败(回滚),核心是保证数据一致性。

1. 核心特性(ACID 属性,必须掌握)

  • 原子性(Atomicity):事务是 "最小单位",不可拆分(如银行转账,扣款和收款要么都成功,要么都失败)。
  • 一致性(Consistency):事务执行前后,数据总状态不变(如转账前 A 有 1000、B 有 500,转账后总和仍为 1500)。
  • 隔离性(Isolation):多个事务并发执行时,互不干扰(如事务 1 未提交的修改,事务 2 不可见)。
  • 持久性(Durability):事务提交后,修改永久保存(即使数据库崩溃,重启后数据仍存在)。

2. 事务隔离级别(解决并发问题)

MySQL 提供 4 种隔离级别,平衡 "一致性" 与 "并发性能":

隔离级别 脏读 不可重复读 幻读 特点与应用场景
READ UNCOMMITTED 允许 允许 允许 性能最高,一致性最差(极少用,如临时统计非核心数据)
READ COMMITTED 禁止 允许 允许 避免脏读,Oracle 默认级别(如普通业务查询,允许同一事务多次读结果不同)
REPEATABLE READ 禁止 禁止 允许 避免脏读、不可重复读,MySQL 默认级别(如订单创建,确保同一事务内数据一致)
SERIALIZABLE 禁止 禁止 禁止 一致性最高,性能最差(如金融交易,禁止并发,避免所有问题)

3. 实战操作(以银行转账为例)

1. 准备环境(创建数据库与表)
复制代码
-- 创建银行数据库
CREATE DATABASE bank CHARACTER SET utf8;
USE bank;

-- 创建账户表
CREATE TABLE accounts (
    account_number INT PRIMARY KEY,  -- 账号
    account_name VARCHAR(100) NOT NULL,  -- 账户名
    balance DECIMAL(15,2) NOT NULL  -- 余额(保留 2 位小数)
);

-- 插入测试数据(A 账号 1001,余额 1000;B 账号 1002,余额 500)
INSERT INTO accounts VALUES (1001, '张三', 1000.00), (1002, '李四', 500.00);
2. 编写事务脚本(转账 200 元:A 扣 200,B 加 200)
复制代码
DELIMITER //
CREATE PROCEDURE sp_transfer_funds(
    IN source_acc INT,  -- 源账号
    IN dest_acc INT,    -- 目标账号
    IN amount DECIMAL(15,2)  -- 转账金额
)
BEGIN
    DECLARE source_balance DECIMAL(15,2);  -- 声明变量存储源账号余额
    DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;  -- 异常时自动回滚

    START TRANSACTION;  -- 开始事务
    SET autocommit = 0;  -- 关闭自动提交(事务内需手动提交)

    -- 1. 查询源账号余额
    SELECT balance INTO source_balance FROM accounts WHERE account_number = source_acc;
    -- 2. 校验余额是否充足,不足则回滚
    IF source_balance < amount THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '余额不足,转账失败';
    END IF;

    -- 3. 源账号扣钱
    UPDATE accounts SET balance = balance - amount WHERE account_number = source_acc;
    -- 4. 目标账号加钱
    UPDATE accounts SET balance = balance + amount WHERE account_number = dest_acc;

    COMMIT;  -- 所有操作成功,提交事务
    SELECT '转账成功' AS result;
END //
DELIMITER ;
3. 调用事务
复制代码
-- 调用转账存储过程(1001 给 1002 转 200)
CALL sp_transfer_funds(1001, 1002, 200.00);

-- 查看转账结果
SELECT * FROM accounts;
4. 事务控制语句
复制代码
-- 开始事务
START TRANSACTION;  -- 或 BEGIN;

-- 提交事务(所有操作生效)
COMMIT;

-- 回滚事务(撤销所有未提交的操作)
ROLLBACK;

-- 设置隔离级别(会话级,仅当前连接有效)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

总结

本文梳理的 MySQL 8 七大核心特性,是数据库设计与开发的 "基石":

  • 约束类(主键、外键、Check):保障数据完整性,防止非法数据;
  • 性能类(索引):提升查询速度,是大数据量场景的 "必备优化手段";
  • 逻辑封装类(存储过程、触发器):简化复杂业务,减少应用与数据库的耦合;
  • 一致性类(事务):确保关键操作(如转账、订单)的原子性与数据安全。
相关推荐
hello 早上好4 小时前
深入 Spring 依赖注入底层原理
数据库·sql·spring
API快乐传递者4 小时前
抓取淘宝商品详情商品数据API接口调用说明文档|获取淘宝商品价格主图数据等
数据库
济南java开发,求内推4 小时前
Redis一个服务器部署多个节点
服务器·数据库·redis
小宁爱Python4 小时前
Windows Docker Desktop占用C盘空间过大解决办法集合
运维·docker·容器
花菜会噎住4 小时前
Django视图与路由全解析:从URL到页面,一篇讲透
数据库·django·sqlite·函数
-雷阵雨-4 小时前
MySQL——数据库约束
数据库·mysql
大筒木老辈子4 小时前
MySQL笔记---C/C++访问MySQL数据库
数据库·笔记·mysql
友友马4 小时前
『 数据库 』MySQL复习(表的约束)
数据库·mysql
恒创科技HK5 小时前
如何选30G、60G、100G的香港高防服务器?
运维·服务器