【趣学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_userorder_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;  

整洁代码七大法则

  1. 格式化是基本礼仪:换行、缩进、对齐三件套
  2. 别名即尊严:用total_amount而非total
  3. 显式连接:让JOIN像高速公路指示牌一样清晰
  4. **禁用SELECT ***:像拒绝陌生人递来的不明食物
  5. 统一命名风格user_id vs uid只能选一个!
  6. 魔法数字退散status = 'active'flag = 1更友好
  7. 排序不用数字下标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"  

三大纪律

  1. 禁止直连生产库改表:SQL脚本必须进版本库
  2. 变更脚本要可重复执行
    CREATE TABLE IF NOT EXISTS users (...);  
    ALTER TABLE users ADD COLUMN IF NOT EXISTS phone...  
    
  3. 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 性能监控与调优——给数据库装上"心电图仪"的硬核指南》的魔幻世界,记得给你的键盘准备按摩仪——优雅编码需要持之以恒! 🧘♂️💻

posted @   爱上编程技术  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示