MySQL 速查手册
MySQL 常用语句、函数、操作速查,支持按版本筛选、搜索和一键复制
数据库操作(5)
表操作(8)
创建表
创建新表,定义字段和主键
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
age INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;查看表结构
显示表的字段定义
DESC users;
-- 或
SHOW COLUMNS FROM users;添加字段
给表新增一个字段
ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;修改字段
修改字段类型或名称
-- 修改类型
ALTER TABLE users MODIFY COLUMN name VARCHAR(200);
-- 改名
ALTER TABLE users CHANGE COLUMN name username VARCHAR(200);删除字段
从表中移除一个字段
ALTER TABLE users DROP COLUMN phone;删除表
删除整个表
DROP TABLE IF EXISTS users;清空表数据
删除所有数据但保留表结构
TRUNCATE TABLE users;重命名表
修改表名
RENAME TABLE users TO members;增删改查(7)
插入数据
向表中插入新记录
INSERT INTO users (name, email, age)
VALUES ('张三', 'zhang@example.com', 25);批量插入
一次插入多条记录
INSERT INTO users (name, email, age) VALUES
('张三', 'zhang@example.com', 25),
('李四', 'li@example.com', 30),
('王五', 'wang@example.com', 28);查询数据
从表中查询记录
SELECT id, name, email FROM users
WHERE age > 18
ORDER BY created_at DESC
LIMIT 10;查询所有字段
查询表中所有字段
SELECT * FROM users;更新数据
修改已有记录
UPDATE users
SET name = '张三丰', age = 30
WHERE id = 1;删除数据
删除符合条件的记录
DELETE FROM users WHERE id = 1;插入或更新
存在则更新,不存在则插入
INSERT INTO users (id, name, email)
VALUES (1, '张三', 'zhang@example.com')
ON DUPLICATE KEY UPDATE
name = VALUES(name),
email = VALUES(email);条件与排序(4)
WHERE 条件
常用查询条件
-- 等于
WHERE name = '张三'
-- 不等于
WHERE age != 18
-- 范围
WHERE age BETWEEN 18 AND 30
-- 包含
WHERE id IN (1, 2, 3)
-- 模糊匹配
WHERE name LIKE '张%'
-- 空值判断
WHERE email IS NOT NULL排序
按字段排序
-- 升序(默认)
ORDER BY age ASC
-- 降序
ORDER BY created_at DESC
-- 多字段排序
ORDER BY age DESC, name ASC分页查询
LIMIT 和 OFFSET 分页
-- 第1页(每页10条)
SELECT * FROM users LIMIT 10 OFFSET 0;
-- 第2页
SELECT * FROM users LIMIT 10 OFFSET 10;
-- 简写
SELECT * FROM users LIMIT 10, 10;去重查询
查询不重复的值
SELECT DISTINCT city FROM users;聚合函数(4)
COUNT 计数
统计记录数量
SELECT COUNT(*) AS total FROM users;
SELECT COUNT(DISTINCT city) AS city_count FROM users;SUM / AVG
求和与平均值
SELECT SUM(amount) AS total, AVG(amount) AS avg_amount
FROM orders;MAX / MIN
最大值与最小值
SELECT MAX(age) AS oldest, MIN(age) AS youngest
FROM users;GROUP BY 分组
按字段分组统计
SELECT city, COUNT(*) AS user_count
FROM users
GROUP BY city
HAVING COUNT(*) > 10
ORDER BY user_count DESC;连接查询(4)
INNER JOIN
内连接,返回两表匹配的记录
SELECT u.name, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id;LEFT JOIN
左连接,返回左表所有记录
SELECT u.name, o.amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;子查询
嵌套查询
SELECT * FROM users
WHERE id IN (
SELECT user_id FROM orders
WHERE amount > 1000
);多表连接
三个表以上的连接
SELECT u.name, o.id, p.product_name
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id
WHERE o.status = 'completed';索引与约束(6)
创建索引
为字段创建索引提升查询速度
-- 普通索引
CREATE INDEX idx_name ON users(name);
-- 唯一索引
CREATE UNIQUE INDEX idx_email ON users(email);
-- 联合索引
CREATE INDEX idx_name_age ON users(name, age);查看索引
查看表的索引信息
SHOW INDEX FROM users;删除索引
移除索引
DROP INDEX idx_name ON users;外键约束
创建外键关联
ALTER TABLE orders
ADD CONSTRAINT fk_user
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE;不可见索引
将索引设为不可见,优化器不使用但保留索引数据,方便测试删除索引的影响
-- 创建不可见索引
ALTER TABLE users ALTER INDEX idx_name INVISIBLE;
-- 恢复可见
ALTER TABLE users ALTER INDEX idx_name VISIBLE;
-- 查看索引可见性
SELECT INDEX_NAME, IS_VISIBLE
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_NAME = 'users';CHECK 约束
8.0.16 起真正强制执行 CHECK 约束(5.7 仅解析不执行)
CREATE TABLE products (
id BIGINT PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(10,2),
CONSTRAINT chk_price CHECK (price > 0)
);
ALTER TABLE users
ADD CONSTRAINT chk_age CHECK (age >= 0 AND age <= 200);常用函数(4)
字符串函数
常用字符串操作
SELECT
CONCAT(first_name, ' ', last_name) AS full_name,
UPPER(name) AS upper_name,
LOWER(name) AS lower_name,
LENGTH(name) AS name_len,
SUBSTRING(name, 1, 3) AS short_name,
REPLACE(email, '@', '[at]') AS safe_email,
TRIM(' hello ') AS trimmed
FROM users;日期函数
日期和时间处理
SELECT
NOW() AS current_time,
CURDATE() AS today,
DATE_FORMAT(created_at, '%Y-%m-%d') AS formatted,
DATEDIFF(NOW(), created_at) AS days_ago,
DATE_ADD(NOW(), INTERVAL 7 DAY) AS next_week,
YEAR(created_at) AS year,
MONTH(created_at) AS month
FROM users;条件函数
IF 和 CASE 条件判断
SELECT name,
IF(age >= 18, '成年', '未成年') AS status,
CASE
WHEN age < 18 THEN '少年'
WHEN age < 40 THEN '青年'
WHEN age < 60 THEN '中年'
ELSE '老年'
END AS age_group
FROM users;类型转换
数据类型转换
SELECT
CAST('123' AS SIGNED) AS int_val,
CAST(price AS CHAR) AS str_val,
CONVERT('2024-01-01', DATE) AS date_val;用户与权限(11)
创建用户
创建新的数据库用户,可指定主机和认证方式
-- 允许任意主机连接
CREATE USER 'appuser'@'%'
IDENTIFIED BY 'StrongPassword123!';
-- 仅允许本地连接
CREATE USER 'localuser'@'localhost'
IDENTIFIED BY 'Password456!';
-- 仅允许指定 IP
CREATE USER 'remote'@'192.168.1.%'
IDENTIFIED BY 'Password789!';查看所有用户
列出服务器上的所有用户账号
-- 查看用户列表
SELECT User, Host, authentication_string
FROM mysql.user;
-- 查看当前用户
SELECT CURRENT_USER();
-- 查看所有用户及最近登录
SELECT User, Host, account_locked, password_expired
FROM mysql.user;授权整个数据库
给用户授权某个数据库的所有权限
-- 所有权限(增删改查+结构操作)
GRANT ALL PRIVILEGES ON mydb.* TO 'appuser'@'%';
-- 只给 CRUD 权限
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'appuser'@'%';
-- 给所有数据库的查询权限
GRANT SELECT ON *.* TO 'readonly'@'%';
-- 刷新权限
FLUSH PRIVILEGES;授权指定表
精细化授权到表级别
-- 只授权某张表的查询
GRANT SELECT ON mydb.users TO 'appuser'@'%';
-- 多张表分别授权
GRANT SELECT, INSERT ON mydb.orders TO 'appuser'@'%';
GRANT SELECT ON mydb.products TO 'appuser'@'%';
-- 授权表的增删改查
GRANT SELECT, INSERT, UPDATE, DELETE
ON mydb.users TO 'appuser'@'%';授权指定列
精细化授权到列级别,限制用户只能操作特定字段
-- 只允许查看 name 和 email 列
GRANT SELECT (name, email) ON mydb.users TO 'appuser'@'%';
-- 只允许更新 email 列
GRANT UPDATE (email) ON mydb.users TO 'appuser'@'%';
-- 只允许插入指定列
GRANT INSERT (name, email) ON mydb.users TO 'appuser'@'%';权限类型详解
MySQL 常用权限类型列表
-- 数据操作权限
-- SELECT 查询数据
-- INSERT 插入数据
-- UPDATE 更新数据
-- DELETE 删除数据
-- 结构操作权限
-- CREATE 创建数据库/表
-- ALTER 修改表结构
-- DROP 删除数据库/表
-- INDEX 创建/删除索引
-- REFERENCES 创建外键
-- 管理权限
-- GRANT OPTION 可将自己的权限授予他人
-- PROCESS 查看所有进程
-- RELOAD 执行 FLUSH
-- SUPER 杀掉其他用户进程
-- CREATE USER 创建/删除用户
-- SHOW DATABASES 查看所有数据库撤销权限
收回用户权限
-- 撤销数据库级别权限
REVOKE ALL PRIVILEGES ON mydb.* FROM 'appuser'@'%';
-- 撤销特定表权限
REVOKE SELECT ON mydb.users FROM 'appuser'@'%';
-- 撤销全局权限
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'appuser'@'%';查看权限
查看用户的权限详情
-- 查看指定用户权限
SHOW GRANTS FOR 'appuser'@'%';
-- 查看当前用户权限
SHOW GRANTS;
-- 从系统表查看库级权限
SELECT * FROM mysql.db WHERE User = 'appuser';
-- 查看表级权限
SELECT * FROM mysql.tables_priv WHERE User = 'appuser';
-- 查看列级权限
SELECT * FROM mysql.columns_priv WHERE User = 'appuser';修改密码
修改用户密码
-- 8.0 推荐方式
ALTER USER 'appuser'@'%'
IDENTIFIED BY 'NewPassword456!';
-- 修改当前用户密码
SET PASSWORD = 'NewPassword456!';
-- 密码过期,强制用户下次登录修改
ALTER USER 'appuser'@'%' PASSWORD EXPIRE;删除用户与锁定
删除用户或锁定/解锁账户
-- 删除用户
DROP USER 'appuser'@'%';
DROP USER IF EXISTS 'tempuser'@'%';
-- 锁定账户(禁止登录)
ALTER USER 'appuser'@'%' ACCOUNT LOCK;
-- 解锁账户
ALTER USER 'appuser'@'%' ACCOUNT UNLOCK;角色管理
8.0 起支持 SQL 角色,批量管理权限
-- 创建角色
CREATE ROLE 'app_read', 'app_write';
-- 给角色授权
GRANT SELECT ON mydb.* TO 'app_read';
GRANT INSERT, UPDATE, DELETE ON mydb.* TO 'app_write';
-- 将角色赋予用户
GRANT 'app_read', 'app_write' TO 'appuser'@'%';
-- 激活角色
SET DEFAULT ROLE ALL TO 'appuser'@'%';
-- 查看角色
SELECT * FROM mysql.role_edges;事务管理(6)
基本事务
BEGIN/COMMIT/ROLLBACK 控制事务
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- 一切正常则提交
COMMIT;
-- 出错则回滚
-- ROLLBACK;SAVEPOINT 保存点
在事务中设置回滚点,可以部分回滚
START TRANSACTION;
INSERT INTO orders (user_id, amount) VALUES (1, 500);
SAVEPOINT sp_order;
INSERT INTO order_items (order_id, product_id) VALUES (100, 5);
-- 这一步出错,只回滚到保存点
ROLLBACK TO sp_order;
-- 保留 orders 的插入
COMMIT;隔离级别
查看和设置事务隔离级别
-- 查看当前隔离级别
SELECT @@transaction_isolation;
-- 设置会话级别
SET SESSION TRANSACTION ISOLATION LEVEL
READ COMMITTED;
-- 四种隔离级别:
-- READ UNCOMMITTED 读未提交(最低)
-- READ COMMITTED 读已提交
-- REPEATABLE READ 可重复读(InnoDB默认)
-- SERIALIZABLE 串行化(最高)自动提交
控制是否自动提交每条 SQL
-- 查看自动提交状态
SELECT @@autocommit;
-- 关闭自动提交(需要手动 COMMIT)
SET autocommit = 0;
-- 开启自动提交
SET autocommit = 1;死锁处理
查看和处理死锁
-- 查看最近的死锁信息
SHOW ENGINE INNODB STATUS;
-- 查看当前锁等待
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
-- 查看正在运行的事务
SELECT * FROM information_schema.INNODB_TRX;
-- 杀掉阻塞的进程
KILL <process_id>;锁操作
手动加表锁和行锁
-- 表锁
LOCK TABLES users READ;
LOCK TABLES users WRITE;
UNLOCK TABLES;
-- 行锁(InnoDB,需在事务中)
SELECT * FROM users WHERE id = 1 FOR UPDATE;
SELECT * FROM users WHERE id = 1 FOR SHARE;视图(2)
创建视图
基于查询创建虚拟表
CREATE VIEW v_active_users AS
SELECT id, name, email, last_login
FROM users
WHERE status = 'active';使用与管理视图
查询视图、查看定义、修改和删除
-- 像普通表一样查询
SELECT * FROM v_active_users WHERE name LIKE '张%';
-- 查看视图定义
SHOW CREATE VIEW v_active_users;
-- 查看所有视图
SELECT TABLE_NAME FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = 'mydb';
-- 修改视图
ALTER VIEW v_active_users AS
SELECT id, name FROM users WHERE status = 'active';
-- 删除视图
DROP VIEW IF EXISTS v_active_users;存储过程与函数(4)
创建存储过程
定义可重复调用的 SQL 程序
DELIMITER //
CREATE PROCEDURE sp_get_user(IN uid BIGINT)
BEGIN
SELECT * FROM users WHERE id = uid;
END //
DELIMITER ;
-- 带输出参数
DELIMITER //
CREATE PROCEDURE sp_count_users(
IN city_name VARCHAR(50),
OUT total INT
)
BEGIN
SELECT COUNT(*) INTO total
FROM users WHERE city = city_name;
END //
DELIMITER ;调用与管理存储过程
调用、查看和删除存储过程
-- 调用存储过程
CALL sp_get_user(1);
-- 带输出参数调用
CALL sp_count_users('北京', @cnt);
SELECT @cnt;
-- 查看存储过程
SHOW PROCEDURE STATUS WHERE Db = 'mydb';
-- 查看定义
SHOW CREATE PROCEDURE sp_get_user;
-- 删除
DROP PROCEDURE IF EXISTS sp_get_user;自定义函数
创建可在 SQL 中调用的自定义函数
DELIMITER //
CREATE FUNCTION fn_full_name(
first_name VARCHAR(50),
last_name VARCHAR(50)
) RETURNS VARCHAR(101)
DETERMINISTIC
BEGIN
RETURN CONCAT(first_name, ' ', last_name);
END //
DELIMITER ;
-- 使用
SELECT fn_full_name('张', '三') AS name;
SELECT fn_full_name(first_name, last_name) FROM users;流程控制
存储过程中的 IF/CASE/WHILE/LOOP
DELIMITER //
CREATE PROCEDURE sp_classify_age(IN uid BIGINT)
BEGIN
DECLARE user_age INT;
DECLARE label VARCHAR(20);
SELECT age INTO user_age FROM users WHERE id = uid;
IF user_age < 18 THEN
SET label = '未成年';
ELSEIF user_age < 60 THEN
SET label = '成年人';
ELSE
SET label = '老年人';
END IF;
SELECT uid, user_age, label;
END //
DELIMITER ;备份与恢复(4)
mysqldump 备份
使用 mysqldump 导出数据库
# 备份单个数据库
mysqldump -u root -p mydb > mydb_backup.sql
# 备份指定表
mysqldump -u root -p mydb users orders > tables_backup.sql
# 备份所有数据库
mysqldump -u root -p --all-databases > all_backup.sql
# 只导出结构(不含数据)
mysqldump -u root -p --no-data mydb > schema.sql
# 只导出数据(不含结构)
mysqldump -u root -p --no-create-info mydb > data.sql恢复数据
从备份文件恢复数据库
# 恢复数据库
mysql -u root -p mydb < mydb_backup.sql
# 恢复时创建数据库
mysql -u root -p < all_backup.sql
# 在 MySQL 内恢复
SOURCE /path/to/backup.sql;导出导入 CSV
导出数据为 CSV 或从 CSV 导入
-- 导出为 CSV(需要 FILE 权限)
SELECT * FROM users
INTO OUTFILE '/tmp/users.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';
-- 从 CSV 导入
LOAD DATA INFILE '/tmp/users.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;二进制日志
查看和管理 binlog,用于增量恢复和主从复制
-- 查看 binlog 是否开启
SHOW VARIABLES LIKE 'log_bin';
-- 查看所有 binlog 文件
SHOW BINARY LOGS;
-- 查看 binlog 内容
SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 20;
-- 用 mysqlbinlog 工具查看
# mysqlbinlog mysql-bin.000001
-- 基于 binlog 做时间点恢复
# mysqlbinlog --start-datetime='2024-01-01 00:00:00' \
# --stop-datetime='2024-01-01 12:00:00' \
# mysql-bin.000001 | mysql -u root -p性能优化(5)
EXPLAIN 分析
分析 SQL 执行计划,发现性能瓶颈
-- 基本用法
EXPLAIN SELECT * FROM users WHERE name = '张三';
-- 详细格式
EXPLAIN FORMAT=JSON
SELECT * FROM users WHERE name = '张三';
-- 关键字段说明:
-- type: ALL(全表扫描) > index > range > ref > eq_ref > const
-- key: 实际使用的索引
-- rows: 预估扫描行数
-- Extra: Using index(覆盖索引), Using filesort(需要排序)慢查询日志
开启和分析慢查询日志
-- 查看慢查询配置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 分析慢查询日志
# mysqldumpslow -s t -t 10 /var/log/mysql/slow.log进程与连接
查看和管理当前连接和查询
-- 查看当前所有进程
SHOW PROCESSLIST;
SHOW FULL PROCESSLIST;
-- 杀掉某个长时间运行的查询
KILL <process_id>;
-- 查看最大连接数
SHOW VARIABLES LIKE 'max_connections';
-- 查看当前连接数
SHOW STATUS LIKE 'Threads_connected';表维护
分析、优化和检查表
-- 分析表(更新索引统计信息)
ANALYZE TABLE users;
-- 优化表(回收碎片空间)
OPTIMIZE TABLE users;
-- 检查表完整性
CHECK TABLE users;
-- 修复表
REPAIR TABLE users;
-- 查看表状态
SHOW TABLE STATUS LIKE 'users';服务器状态
查看 MySQL 服务器运行状态和变量
-- 查看 InnoDB 引擎状态
SHOW ENGINE INNODB STATUS;
-- 查看全局状态变量
SHOW GLOBAL STATUS;
-- 查看缓冲池命中率
SHOW STATUS LIKE 'Innodb_buffer_pool%';
-- 查看系统变量
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
-- 查看表空间使用
SELECT table_name,
ROUND(data_length/1024/1024, 2) AS data_mb,
ROUND(index_length/1024/1024, 2) AS index_mb
FROM information_schema.tables
WHERE table_schema = 'mydb'
ORDER BY data_length DESC;窗口函数(5)
ROW_NUMBER
为结果集中的每一行分配唯一的行号
SELECT
name, department, salary,
ROW_NUMBER() OVER (
PARTITION BY department
ORDER BY salary DESC
) AS rn
FROM employees;RANK / DENSE_RANK
排名函数,RANK 有间隔,DENSE_RANK 无间隔
SELECT name, score,
RANK() OVER (ORDER BY score DESC) AS rank_with_gap,
DENSE_RANK() OVER (ORDER BY score DESC) AS rank_no_gap
FROM students;LAG / LEAD
访问当前行前后的行数据,常用于同比/环比
SELECT
month, revenue,
LAG(revenue, 1) OVER (ORDER BY month) AS prev_month,
revenue - LAG(revenue, 1) OVER (ORDER BY month) AS growth
FROM monthly_sales;SUM / AVG OVER
窗口聚合:累计求和、移动平均等
SELECT
order_date, amount,
SUM(amount) OVER (ORDER BY order_date) AS running_total,
AVG(amount) OVER (
ORDER BY order_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS moving_avg_7d
FROM orders;NTILE
将结果集均匀分成 N 个桶
SELECT name, salary,
NTILE(4) OVER (ORDER BY salary DESC) AS quartile
FROM employees;CTE 公用表表达式(3)
基本 CTE
WITH 子句定义临时结果集,提升可读性
WITH active_users AS (
SELECT * FROM users
WHERE status = 'active'
AND last_login > DATE_SUB(NOW(), INTERVAL 30 DAY)
)
SELECT department, COUNT(*) AS cnt
FROM active_users
GROUP BY department;多 CTE 组合
一次定义多个 CTE 并关联使用
WITH
dept_stats AS (
SELECT department_id, AVG(salary) AS avg_sal
FROM employees GROUP BY department_id
),
high_earners AS (
SELECT e.*, d.avg_sal
FROM employees e
JOIN dept_stats d ON e.department_id = d.department_id
WHERE e.salary > d.avg_sal * 1.5
)
SELECT * FROM high_earners ORDER BY salary DESC;递归 CTE
递归查询,适合处理层级/树形结构数据
WITH RECURSIVE org_tree AS (
-- 锚定成员:找到根节点
SELECT id, name, manager_id, 1 AS level
FROM employees WHERE manager_id IS NULL
UNION ALL
-- 递归成员:逐层展开
SELECT e.id, e.name, e.manager_id, t.level + 1
FROM employees e
JOIN org_tree t ON e.manager_id = t.id
)
SELECT * FROM org_tree ORDER BY level, name;JSON 操作(5)
JSON 列与基本操作
创建 JSON 类型列,存取 JSON 数据
CREATE TABLE events (
id BIGINT PRIMARY KEY,
data JSON NOT NULL
);
INSERT INTO events VALUES
(1, '{"type": "click", "page": "/home"}');
-- 提取值
SELECT
data->>'$.type' AS event_type,
data->>'$.page' AS page
FROM events;JSON 查询函数
JSON_EXTRACT, JSON_CONTAINS 等查询函数
-- 提取
SELECT JSON_EXTRACT(data, '$.tags[0]') FROM events;
-- ->> 是 JSON_UNQUOTE(JSON_EXTRACT(...)) 的简写
SELECT data->>'$.name' FROM events;
-- 包含判断
SELECT * FROM events
WHERE JSON_CONTAINS(data, '"click"', '$.type');
-- 键是否存在
SELECT * FROM events
WHERE JSON_CONTAINS_PATH(data, 'one', '$.email');JSON 修改函数
JSON_SET, JSON_INSERT, JSON_REMOVE 等修改函数
-- 设置(存在则覆盖,不存在则新增)
UPDATE events SET data = JSON_SET(data, '$.status', 'done');
-- 插入(仅不存在时新增)
UPDATE events SET data = JSON_INSERT(data, '$.priority', 'high');
-- 删除
UPDATE events SET data = JSON_REMOVE(data, '$.temp');
-- 数组追加
UPDATE events SET data = JSON_ARRAY_APPEND(data, '$.tags', 'new');JSON_TABLE
将 JSON 数据展开为关系表行列,便于 JOIN 和聚合
SELECT jt.*
FROM events,
JSON_TABLE(
data, '$.items[*]' COLUMNS (
item_id INT PATH '$.id',
item_name VARCHAR(100) PATH '$.name',
quantity INT PATH '$.qty' DEFAULT '0' ON EMPTY
)
) AS jt
WHERE jt.quantity > 0;JSON Schema 校验
使用 JSON_SCHEMA_VALID 在插入时校验 JSON 格式
ALTER TABLE events ADD CONSTRAINT chk_data
CHECK (JSON_SCHEMA_VALID('{
"type": "object",
"required": ["type", "page"],
"properties": {
"type": {"type": "string"},
"page": {"type": "string"}
}
}', data));