课程 10.1 · 阅读时间:~9分钟
本课程涵盖编写高质量SQL代码的基础知识,使其易于阅读和维护。您将学习格式化标准、对象命名规则以及如何有效使用注释。我们将回顾如何使复杂查询对您的团队成员和未来的自己清晰易懂。到本课程结束时,您将能够专业且一致地格式化SQL脚本。
课程10.1:可读性和可维护性SQL代码的最佳实践
在上一个模块中,我们学习了视图和临时表等高级数据工具。现在,随着您的查询变得越来越大和复杂,代码质量成为首要任务。在实际的分析和开发工作中,SQL代码的阅读频率远高于编写频率。
结构良好的代码减少错误,简化调试,并为整个团队节省时间。这不仅仅是风格问题。这是任何SQL开发人员或数据分析师的关键技能。
为什么代码风格很重要
当查询有5-10行时,其逻辑通常一目了然。但当您转向包含许多JOIN子句、子查询或CTE块的复杂报告时,代码可能会变得过于复杂,甚至对于原作者在一周后也难以解析。
遵循标准可以帮助您:
- 更快找到错误: 错误的过滤器或缺失的
JOIN子句在干净的代码中会显得突出。 - 扩展解决方案: 结构化代码更容易扩展新字段和条件。
- 团队协作: 团队成员可以更顺利地审查和维护您的脚本。
格式化和缩进
一致的格式化风格是可读性的基础。SQL对空格或字母大小写不敏感,但有广泛接受的约定。
关键字大小写
一个常见的做法是将SQL关键字(SELECT、FROM、WHERE、JOIN、GROUP BY)写成大写。这在视觉上将数据库命令与表和列名称分开。
-- 差
select name, price from products where category_id = 1;
-- 更好
SELECT name, price
FROM products
WHERE category_id = 1;
换行和缩进
每个主要子句应在新行开始。如果SELECT或GROUP BY包含许多列,则将每列放在自己的行上。
SELECT
customer_id,
first_name,
last_name,
email
FROM customer
WHERE active = 1
ORDER BY last_name;
命名约定
为表、列和变量选择良好的名称对代码清晰度至关重要。
小写和snake_case
在SQL中,事实上的标准是使用小写和单词之间的下划线。许多DBMS引擎以不同的方式规范标识符的大小写(例如,PostgreSQL和Oracle),而snake_case有助于避免混淆。
- 差:
CustomerOrders、TotalAmount - 更好:
customer_orders、total_amount
对象类型的前缀
有时团队使用前缀快速识别对象类型。
示例:
v_表示视图:v_active_customerstmp_表示临时表:tmp_monthly_reportt_表示基础表(较少使用)
-- 这显然是一个准备好的视图
SELECT *
FROM v_customer_payment_summary
WHERE total_amount > 100;
命名和别名
清晰的名称和别名使查询自我文档化。
清晰的表别名
使用简短但有意义的别名,特别是在JOIN时。避免使用t1、t2、a、b等别名。
-- 不清晰
SELECT
t1.name,
t2.amount
FROM table_a t1
JOIN table_b t2 ON t1.id = t2.ref_id;
-- 清晰
SELECT
c.first_name,
p.amount
FROM customer c
JOIN payment p ON c.customer_id = p.customer_id;
计算字段的清晰别名
始终为聚合和计算列提供有意义的名称。名为count(*)的报告列看起来不专业。
SELECT
category_id,
COUNT(*) AS total_films_in_category,
AVG(replacement_cost) AS average_replacement_cost
FROM film
GROUP BY category_id;
注释SQL代码
注释解释为什么某段逻辑存在,当意图不明显时。
- 单行注释(
--): 解释特定的过滤器或公式。 - 块注释(
/* ... */): 描述脚本目的、作者和日期。
/*
脚本:每月活跃客户消费
作者:Ivanov I.
日期:2026-04-16
*/
SELECT
customer_id,
SUM(amount) AS monthly_spent
FROM payment
WHERE payment_date >= '2026-01-01' -- 从年初开始过滤
AND payment_date < '2026-02-01'
GROUP BY customer_id;
实际示例:清理混乱的查询
让我们比较一个难以阅读的查询与一个可维护的版本。
之前(难以阅读):
select f.title,c.name,count(r.rental_id) from film f join film_category fc on f.film_id=fc.film_id join category c on fc.category_id=c.category_id join inventory i on f.film_id=i.film_id join rental r on i.inventory_id=r.inventory_id group by f.title,c.name having count(r.rental_id)>30 order by count(r.rental_id) desc;
之后(易于维护):
SELECT
f.title,
c.name AS category_name,
COUNT(r.rental_id) AS rental_count
FROM film f
JOIN film_category fc ON f.film_id = fc.film_id
JOIN category c ON fc.category_id = c.category_id
JOIN inventory i ON f.film_id = i.film_id
JOIN rental r ON i.inventory_id = r.inventory_id
GROUP BY f.title, c.name
HAVING COUNT(r.rental_id) > 30
ORDER BY rental_count DESC;
注意:在第二个版本中,关系结构、聚合命名和过滤逻辑立即可见。
本课的关键要点:
- 将SQL关键字写成大写,以使查询结构可见。
- 使用换行和缩进,使长查询更易于阅读和审查。
- 为表和计算字段使用清晰的别名。
- 应用一致的命名规则,例如表和列的
snake_case。 - 注释不明显的业务逻辑和复杂的过滤条件。
- 在团队中维护共享的风格指南,以加快审查、调试和演变。
常见问题
SQL关键字是否总需要大写?
没有技术要求。DBMS引擎也会解析小写。但一致的大写风格(SELECT、FROM、WHERE、JOIN)提高了可读性并加快了长查询的审查。
SQL中的注释何时真正有用?
注释在逻辑不明显的地方最有用:业务规则、不寻常的过滤器和技术限制。如果代码已经清晰,请避免不必要的注释。
对于可维护性,格式化和命名哪个更重要?
两者都至关重要。格式化快速显示查询结构,而清晰的名称和别名使意图显而易见,无需额外解释。
面试问题
可维护的SQL代码的特征是什么?
可维护的SQL具有一致的格式、清晰的命名、有意义的别名和在不明显的地方简洁的注释。这使得代码更容易审查、修改和支持团队。
为什么糟糕的命名会成为团队级别的问题?
不清晰的名称和别名会减慢审查速度,并增加在更改过程中出错的风险。良好的名称减少了认知负担,使查询逻辑透明。
您将如何在实践中改进混乱的SQL查询?
首先将其拆分为逻辑块(SELECT、FROM、JOIN、WHERE、GROUP BY、ORDER BY),并进行适当的换行和缩进。然后替换不清晰的别名,清晰命名计算字段,并在逻辑不明显的地方添加简短的注释。
在下一课中,我们将转向技术优化,学习如何编写不仅干净而且快速的SQL查询。