【趣学SQL】第八章:SQL 实战案例 8.1 编写可维护的 SQL 代码——从“代码屎山“到“代码花园“的改造指南
第八章:SQL 最佳实践
8.1 编写可维护的 SQL 代码——从"代码屎山"到"代码花园"的改造指南
欢迎来到「SQL代码整形医院」!今天我们将化身"代码园丁",用一家因SQL代码混乱导致全员加班的虚拟电商公司案例,教你如何把"祖传屎山代码"修剪成"清爽可维护的艺术品"。🌿🧑💻
8.1.1 代码整洁的原则——SQL界的"优雅八荣八耻"
案例:一段让同事想拔刀的代码
SELECT a.id,b.total,c.name FROM tbl_user a JOIN order_tbl b ON a.id=b.uid JOIN item c ON b.iid=c.id WHERE a.flag=1 AND b.ctime>'2023-01-01' ORDER BY 2 DESC LIMIT 100;
问题诊断报告:
- 表别名
a/b/c
像摩斯密码 tbl_user
和order_tbl
命名风格精分ORDER BY 2
是隐藏的定时炸弹- 字段挤成一团像沙丁鱼罐头
整形手术方案:
-- 目标:查询活跃用户的订单排行榜
SELECT
users.user_id AS user_id, -- 用户ID
orders.total_amount AS pay_total,
items.item_name AS product_name
FROM
users
INNER JOIN orders
ON users.user_id = orders.user_id
INNER JOIN items
ON orders.item_id = items.item_id
WHERE
users.status = 'active'
AND orders.created_time > '2023-01-01'
ORDER BY
orders.total_amount DESC -- 按支付金额降序
LIMIT 100;
整洁代码七大法则:
- 格式化是基本礼仪:换行、缩进、对齐三件套
- 别名即尊严:用
total_amount
而非total
- 显式连接:让
JOIN
像高速公路指示牌一样清晰 - **禁用SELECT ***:像拒绝陌生人递来的不明食物
- 统一命名风格:
user_id
vsuid
只能选一个! - 魔法数字退散:
status = 'active'
比flag = 1
更友好 - 排序不用数字下标:
ORDER BY 2
是同事友谊的粉碎机
8.1.2 使用注释——给代码装上"导航语音包"
反面教材集锦(注释的七宗罪)
-- 罪状1:废话文学奖
SELECT user_id FROM users; -- 这里查询用户ID
-- 罪状2:考古注释
/* 2015年王工写的 千万别改! */
-- (实际代码已被改过20次)
-- 罪状3:发泄式TODO
# TODO:这坨代码需要重构(然后三年没动)
正确姿势示范(注释三原则)
/*
[LTV计算逻辑]
目标:计算用户生命周期价值
业务规则:
- 仅统计近3年有消费用户
- 退款订单需扣除金额
版本记录:
- 2023-05 初版(张小明)
- 2024-02 增加汇率转换逻辑
*/
WITH user_orders AS (
-- 步骤1:清洗有效订单数据
SELECT
user_id,
SUM(
CASE
WHEN currency = 'USD' THEN amount * 7.2
ELSE amount
END
) AS total_cny
FROM
orders
WHERE
order_status NOT IN ('cancelled', 'refunded')
AND created_time > CURRENT_DATE - INTERVAL 3 YEAR
GROUP BY
user_id
)
...
8.1.3 代码复用——拒绝做"CTRL+C/V工程师"
典型病变案例(重复代码扩散)
-- 文件:promotion_analysis.sql
SELECT AVG(amount) FROM orders
WHERE created_time BETWEEN '2024-06-01' AND '2024-06-18'
AND amount > 100;
-- 文件:quarter_report.sql
SELECT AVG(amount) FROM orders
WHERE created_time BETWEEN '2024-04-01' AND '2024-06-30'
AND amount > 100;
重构手术方案:
-- 创建可配置视图
CREATE VIEW high_value_orders AS
SELECT *
FROM orders
WHERE amount > 100; -- 高价值订单定义
-- 复用案例
SELECT
AVG(amount) AS avg_amount,
COUNT(*) AS order_count
FROM
high_value_orders
WHERE
created_time BETWEEN @start_date AND @end_date;
-- 进阶版:参数化存储过程
DELIMITER $$
CREATE PROCEDURE GetOrderStats(
IN start_date DATE,
IN end_date DATE
)
BEGIN
SELECT
AVG(amount) AS avg_amount,
COUNT(*) AS order_count
FROM
high_value_orders
WHERE
created_time BETWEEN start_date AND end_date;
END$$
DELIMITER ;
8.1.4 代码审查——用"X光眼"做代码安检
Code Review Checklist(毒舌版)
1. [ ] 有没有人偷偷用了SELECT *?(抓住罚款50)
2. [ ] WHERE条件字段穿"索引外套"了吗?
3. [ ] 事务范围是不是比老板的胃还大?
4. [ ] 有没有在SQL里写业务逻辑(判死刑!)
5. [ ] 分页查询是不是用的自杀式LIMIT?
6. [ ] 字段别名有没有用`a1/a2`这类密码?
7. [ ] 有没有处理NULL值这个"隐形杀手"?
审查实战(吐槽大会版)
-- 提交的代码:
SELECT
u.id,
o.total
FROM
user u
JOIN order o ON u.id = o.uid
WHERE
o.time > '2024-01-01';
-- 审查员毒舌点评:
1. 💣 表别名`u/o`是要参加极简主义大赛吗?
2. 💣 `user`表字段`id`和`order`表`uid`命名精分
3. 💣 没有指定排序规则,结果随机跳舞吗?
4. 💣 时间字段没有索引,查询准备跑一年?
8.1.5 版本控制——给SQL穿上"时空防护服"
错误示范(血的教训)
# 生产环境直接操作
mysql> ALTER TABLE users ADD COLUMN phone VARCHAR(20);
Query OK, 0 rows affected (30 min 22.34 sec)
-- 然后忘记在其他环境执行,导致测试环境爆炸
正确姿势(Git流最佳实践)
📦sql_scripts
├── 📂ddl
│ └── 20240301_alter_users_add_phone.sql
├── 📂dml
│ └── 20240302_backfill_user_phones.sql
└── 📂procedures
└── sp_get_order_stats.sql
提交示例:
git commit -m "feat: 新增用户手机号字段
- 新增phone字段存储加密手机号
- 添加唯一索引防止重复
- 相关文档见Wiki #123"
三大纪律:
- 禁止直连生产库改表:SQL脚本必须进版本库
- 变更脚本要可重复执行:
CREATE TABLE IF NOT EXISTS users (...); ALTER TABLE users ADD COLUMN IF NOT EXISTS phone...
- DDL/DML分离管理:结构变更与数据操作分家
防崩溃小贴士
自动化工具套餐:
# SQL格式化神器
sqlformat --keywords upper -r ugly.sql > beautiful.sql
# 版本差异对比
git diff --word-diff HEAD~1:ugly.sql ugly.sql
# 预提交检查
pre-commit run sqlfluff
本章冷知识
- 最长的SQL文件吉尼斯纪录:某ERP系统单个文件3万行(建议不要尝试)
- Git最初是为管理Linux内核代码而生,现在连SQL脚本都能管
- 某公司因SQL代码没有版本控制,误删表后花50万找数据恢复公司
现在你已经成为"SQL代码美容大师"!下一章我们将进入《SQL 性能监控与调优——给数据库装上"心电图仪"的硬核指南》的魔幻世界,记得给你的键盘准备按摩仪——优雅编码需要持之以恒! 🧘♂️💻
代码学习,前言技术分享,深度分析编程技术,普及科普编程技术,天天都要敲代码
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)