外观
PostgreSQL SQL书写规范
1. 命名规范
1.1 数据库对象命名
| 对象类型 | 命名规则 | 示例 |
|---|---|---|
| 数据库 | 小写字母+下划线,业务相关 | ecommerce_db |
| 模式 | 小写字母+下划线,功能模块相关 | sales_schema |
| 表 | 小写字母+下划线,复数形式 | orders, users |
| 视图 | 小写字母+下划线,v_前缀 | v_active_orders |
| 索引 | 小写字母+下划线,idx_表名_字段名 | idx_orders_customer_id |
| 函数 | 小写字母+下划线,动词开头 | get_user_by_id() |
| 存储过程 | 小写字母+下划线,sp_前缀 | sp_process_order() |
| 序列 | 小写字母+下划线,表名_id_seq | orders_order_id_seq |
| 触发器 | 小写字母+下划线,tr_表名_事件 | tr_orders_after_insert |
1.2 列命名
- 使用小写字母+下划线
- 避免使用保留字
- 保持命名简洁明确
- 使用有意义的名称,避免缩写
推荐:
sql
user_id, order_date, total_amount不推荐:
sql
uid, od, tamt -- 缩写不明确2. 格式规范
2.1 基本格式
- 关键字大写
- 缩进使用4个空格(避免使用制表符)
- 逗号放在行尾
- 每行长度不超过120个字符
示例:
sql
SELECT
o.order_id,
o.customer_id,
u.username,
o.total_amount,
o.order_date
FROM
orders o
JOIN
users u ON o.customer_id = u.user_id
WHERE
o.order_date >= '2024-01-01'
AND o.status = 'completed'
ORDER BY
o.order_date DESC
LIMIT 100;2.2 复杂查询格式
- 子查询、CTE单独成行
- JOIN条件每行一个
- WHERE条件按逻辑分组
- 函数调用参数换行对齐
示例:
sql
WITH recent_orders AS (
SELECT
order_id,
customer_id,
total_amount
FROM
orders
WHERE
order_date >= NOW() - INTERVAL '30 days'
)
SELECT
c.customer_id,
c.customer_name,
COUNT(ro.order_id) AS order_count,
SUM(ro.total_amount) AS total_spent
FROM
customers c
LEFT JOIN
recent_orders ro ON c.customer_id = ro.customer_id
GROUP BY
c.customer_id,
c.customer_name
HAVING
COUNT(ro.order_id) > 0
ORDER BY
total_spent DESC
LIMIT 20;2.3 DDL语句格式
sql
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
last_login TIMESTAMP,
is_active BOOLEAN NOT NULL DEFAULT true,
role VARCHAR(20) NOT NULL DEFAULT 'user'
);
CREATE INDEX idx_users_email ON users (email);3. 性能优化规范
3.1 SELECT语句优化
只查询需要的列:避免使用
SELECT *sql-- 推荐 SELECT user_id, username FROM users; -- 不推荐 SELECT * FROM users;使用LIMIT限制返回行数:特别是在开发和调试阶段
sqlSELECT * FROM large_table LIMIT 100;避免在WHERE子句中使用函数:会导致索引失效
sql-- 推荐 SELECT * FROM orders WHERE order_date >= '2024-01-01'; -- 不推荐 SELECT * FROM orders WHERE DATE(order_date) = '2024-01-01';使用JOIN替代子查询:在大多数情况下JOIN性能更好
sql-- 推荐 SELECT o.* FROM orders o JOIN users u ON o.customer_id = u.user_id WHERE u.username = 'john'; -- 不推荐 SELECT * FROM orders WHERE customer_id IN (SELECT user_id FROM users WHERE username = 'john');
3.2 索引使用规范
- 为WHERE子句中的列创建索引
- 为JOIN条件中的列创建索引
- 为ORDER BY和GROUP BY列创建索引
- 避免创建过多索引:每个表建议不超过5个索引
- 使用复合索引时,将高选择性列放在前面
3.3 事务处理规范
- 保持事务简短:减少锁持有时间
- 明确指定事务隔离级别:根据业务需求选择合适的隔离级别
- 避免在事务中执行DDL语句:会导致隐式提交
- 使用SAVEPOINT进行部分回滚:在复杂事务中使用
sql
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 业务逻辑
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;4. 安全规范
4.1 防止SQL注入
- 使用参数化查询:避免直接拼接SQL语句
- 验证输入数据:对用户输入进行严格验证
- 使用最小权限原则:为应用程序分配最小必要权限
4.2 敏感数据处理
- 避免明文存储敏感数据:使用加密函数存储密码等敏感信息
- 使用列级权限:限制对敏感列的访问
- 审计敏感操作:记录对敏感数据的访问和修改
sql
-- 推荐
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
password_hash VARCHAR(255) NOT NULL -- 存储哈希值
);
-- 不推荐
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
password VARCHAR(50) NOT NULL -- 明文存储
);5. 最佳实践
5.1 代码复用
- 使用视图封装复杂查询
- 使用函数和存储过程封装业务逻辑
- 使用CTE简化复杂查询
5.2 注释规范
- 为复杂查询添加注释
- 为函数和存储过程添加文档注释
- 说明业务逻辑和特殊处理
sql
-- 查询最近30天的订单统计数据
SELECT
DATE(order_date) AS order_day,
COUNT(*) AS order_count,
SUM(total_amount) AS total_sales
FROM
orders
WHERE
order_date >= NOW() - INTERVAL '30 days'
GROUP BY
DATE(order_date)
ORDER BY
order_day;5.3 版本兼容性
- 避免使用特定版本的功能:如需要使用,添加版本检查
- 使用标准SQL语法:提高代码可移植性
- 测试不同版本的兼容性
5.4 测试规范
- 为复杂查询编写测试用例
- 测试边界条件
- 测试性能和并发情况
6. 常见错误与规避
6.1 空值处理
- 正确使用
IS NULL和IS NOT NULL - 避免使用
=或!=比较NULL值 - 考虑使用
COALESCE()函数处理NULL值
sql
-- 推荐
SELECT * FROM users WHERE last_login IS NULL;
-- 不推荐
SELECT * FROM users WHERE last_login = NULL;6.2 数据类型匹配
- 确保比较的数据类型一致
- 避免隐式类型转换
- 使用显式类型转换函数
sql
-- 推荐
SELECT * FROM orders WHERE order_id = 123;
-- 不推荐
SELECT * FROM orders WHERE order_id = '123'; -- 隐式转换6.3 锁竞争
- 避免长时间持有锁
- 减少事务中的操作数量
- 使用合适的锁级别
7. 版本差异注意事项
| 功能 | PostgreSQL版本 | 注意事项 |
|---|---|---|
| JSONB支持 | 9.4+ | 9.4之前使用JSON类型 |
| 并行查询 | 9.6+ | 9.6之前不支持并行执行 |
| 分区表支持 | 10+ | 10之前使用继承表实现分区 |
| 物化视图自动刷新 | 13+ | 13之前需要手动刷新 |
| 原生表压缩 | 14+ | 14之前使用外部工具压缩 |
8. 工具推荐
8.1 SQL格式化工具
- pgFormatter:PostgreSQL专用SQL格式化工具
- SQLFluff:支持多种数据库的SQL lint工具
- dbeaver:集成开发环境,支持SQL格式化
8.2 性能分析工具
- EXPLAIN ANALYZE:内置查询计划分析工具
- pg_stat_statements:查询统计扩展
- pgBadger:日志分析工具
9. 代码审查要点
- 命名规范:检查数据库对象和列命名是否符合规范
- 格式规范:检查SQL格式是否统一
- 性能问题:检查是否存在性能瓶颈
- 安全问题:检查是否存在SQL注入风险
- 可维护性:检查代码是否易于理解和维护
- 版本兼容性:检查是否兼容目标PostgreSQL版本
10. 总结
良好的SQL书写规范对于数据库的性能、可维护性和安全性至关重要。通过遵循本规范,可以:
- 提高SQL代码的可读性和可维护性
- 减少性能问题和安全漏洞
- 提高团队协作效率
- 确保数据库的长期稳定运行
建议将本规范作为团队SQL开发的标准,并定期进行培训和代码审查,持续改进SQL开发质量。
