MySQL 8 默认认证插件是 caching_sha2_password(比旧的 mysql_native_password 更安全)。在老客户端(尤其老驱动)连接时可能需要升级驱动或显式配置。
同时 MySQL 8 引入了 角色(Roles),让权限治理从“给人授权”升级为“给角色授权,再把角色赋给人”。
2) 面向开发者的 SQL 能力升级(最值得学)
2.1 CTE(Common Table Expression,WITH)
CTE 的价值是:把复杂查询拆成“具名的中间结果”,可读性与可维护性显著提升。
例 1:用 CTE 拆分复杂逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14
WITH paid_orders AS ( SELECT id, user_id, amount, paid_at FROM orders WHERE status ='PAID' ), recent_paid AS ( SELECT* FROM paid_orders WHERE paid_at >= NOW() -INTERVAL30DAY ) SELECT user_id, COUNT(*) AS cnt, SUM(amount) AS total FROM recent_paid GROUPBY user_id ORDERBY total DESC;
例 2:递归 CTE(树/层级结构)
适合查组织架构、分类树、评论树等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
WITHRECURSIVE category_tree AS ( SELECT id, parent_id, name, 0AS depth FROM categories WHERE id =100
UNIONALL
SELECT c.id, c.parent_id, c.name, t.depth +1 FROM categories c JOIN category_tree t ON c.parent_id = t.id ) SELECT* FROM category_tree ORDERBY depth, id;
2.2 窗口函数(Window Functions)
窗口函数是 MySQL 8 的“生产力神器”:在不丢失明细行的情况下,做排名、累计、分组统计。
例 1:每个部门工资排名
1 2 3 4 5 6
SELECT emp_id, dept_id, salary, DENSE_RANK() OVER (PARTITIONBY dept_id ORDERBY salary DESC) AS rk FROM employee;
例 2:按日期做累计(running total)
1 2 3 4 5 6
SELECT dt, amount, SUM(amount) OVER (ORDERBY dt) AS running_total FROM daily_sales ORDERBY dt;
例 3:取“每组 Top N”(常见报表需求)
1 2 3 4 5 6 7 8 9 10 11 12
WITH ranked AS ( SELECT user_id, amount, created_at, ROW_NUMBER() OVER (PARTITIONBY user_id ORDERBY created_at DESC) AS rn FROM payments ) SELECT* FROM ranked WHERE rn <=3 ORDERBY user_id, rn;
GRANT'app_read'TO'app_user'@'%'; SETDEFAULT ROLE 'app_read'TO'app_user'@'%';
查看当前权限:
1
SHOW GRANTS FOR'app_user'@'%';
5) 常用 SQL 示例(按真实业务场景)
5.1 去重与最近一条(每个用户最新订单)
MySQL 8 之前常用“自连接 + MAX”,MySQL 8 可以直接用窗口函数:
1 2 3 4 5 6 7 8 9
WITH ranked AS ( SELECT o.*, ROW_NUMBER() OVER (PARTITIONBY user_id ORDERBY created_at DESC) AS rn FROM orders o ) SELECT* FROM ranked WHERE rn =1;
5.2 分段统计(按月汇总 + 同比/环比)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
WITH m AS ( SELECT DATE_FORMAT(paid_at, '%Y-%m') AS ym, SUM(amount) AS total FROM orders WHERE status ='PAID' GROUPBY DATE_FORMAT(paid_at, '%Y-%m') ) SELECT ym, total, LAG(total, 1) OVER (ORDERBY ym) AS prev_month_total, total -LAG(total, 1) OVER (ORDERBY ym) AS mom_delta FROM m ORDERBY ym;