Skip to content

Oracle SQL编写规范

命名规范

表和列命名

  • 使用有意义的表名和列名
  • 表名使用复数形式
  • 列名使用单数形式
  • 使用下划线分隔单词
  • 避免使用保留字
  • 统一命名风格(如全部小写或全部大写)

索引和约束命名

  • 索引命名:IX_表名_列名
  • 主键约束:PK_表名
  • 外键约束:FK_表名_关联表名
  • 唯一约束:UK_表名_列名
  • 检查约束:CK_表名_列名

存储过程和函数命名

  • 存储过程:PROC_功能描述
  • 函数:FUNC_功能描述
  • 包:PKG_功能描述
  • 触发器:TRG_表名_触发事件

格式规范

缩进和换行

  • 使用 4 个空格作为缩进
  • 关键字大写,表名和列名小写
  • 每个子句单独一行
  • 运算符前后添加空格
  • 逗号后添加空格

代码示例

sql
SELECT
    employee_id,
    first_name,
    last_name,
    hire_date
FROM
    employees
WHERE
    department_id = 100
    AND salary > 5000
ORDER BY
    last_name;

注释规范

  • 单行注释:-- 注释内容
  • 多行注释:/* 注释内容 */
  • 注释应清晰说明 SQL 语句的目的
  • 复杂 SQL 语句应添加详细注释
  • 注释应与代码保持同步更新

性能规范

索引使用

  • 避免全表扫描:SELECT * FROM employees;
  • 使用索引列作为 WHERE 条件
  • 避免在索引列上使用函数:SELECT * FROM employees WHERE UPPER(last_name) = 'SMITH';
  • 合理设计复合索引,考虑列的顺序
  • 定期分析索引使用情况:SELECT * FROM v$object_usage;

SQL 语句优化

  • 使用绑定变量:SELECT * FROM employees WHERE employee_id = :emp_id;
  • 避免使用 SELECT *,只选择需要的列
  • 使用 EXISTS 替代 IN,特别是子查询结果集较大时
  • 使用 UNION ALL 替代 UNION,如果不需要去重
  • 避免使用 HAVING 子句,尽量使用 WHERE 子句

连接查询优化

  • 优先使用 JOIN 语法,避免使用逗号分隔表
  • 合理选择连接类型:INNER JOIN, LEFT JOIN, RIGHT JOIN
  • 小表驱动大表,减少连接操作的开销
  • 避免笛卡尔积:确保连接条件完整
  • 使用 ANSI 标准连接语法

子查询优化

  • 尽量使用内联视图替代嵌套子查询
  • 避免多层嵌套子查询
  • 考虑使用 WITH 子句(公用表表达式)提高可读性
  • 子查询应返回最小必要的结果集

安全规范

防止 SQL 注入

  • 使用绑定变量:SELECT * FROM employees WHERE employee_id = :emp_id;
  • 避免拼接 SQL 语句:'SELECT * FROM employees WHERE employee_id = ' || emp_id;
  • 对用户输入进行验证和过滤
  • 使用存储过程处理复杂操作
  • 限制用户权限,遵循最小权限原则

数据访问控制

  • 避免使用 SYSTEMSYS 账户执行应用操作
  • 使用角色管理权限,避免直接授权
  • 限制敏感数据的访问
  • 对敏感数据使用加密
  • 审计敏感操作

错误处理

  • 使用异常处理:EXCEPTION WHEN OTHERS THEN ...
  • 避免使用 WHEN OTHERS THEN NULL; 吞掉异常
  • 记录详细的错误信息
  • 提供友好的错误提示
  • 定期检查错误日志

可靠性规范

事务管理

  • 保持事务简短,减少锁定时间
  • 使用 COMMITROLLBACK 明确结束事务
  • 避免长事务,特别是在高并发环境
  • 使用 SAVEPOINT 进行部分回滚
  • 考虑使用 SET TRANSACTION 设置事务属性

数据完整性

  • 使用约束确保数据完整性:主键、外键、唯一约束、检查约束
  • 避免使用触发器维护数据完整性,优先使用约束
  • 对重要数据进行双重验证
  • 定期检查数据一致性
  • 使用 VALIDATE CONSTRAINT 验证约束有效性

错误预防

  • 使用 NULL 值处理:NVL, COALESCE
  • 避免除以零错误:NULLIF
  • 处理大型对象时注意大小限制
  • 避免日期格式错误,使用 TO_DATE 明确指定格式
  • 验证输入参数的有效性

可维护性规范

代码组织

  • 使用一致的代码结构
  • 将复杂 SQL 语句分解为多个步骤
  • 使用视图简化复杂查询
  • 合理使用存储过程和函数
  • 模块化设计,避免重复代码

文档和注释

  • 为复杂 SQL 语句添加注释
  • 记录 SQL 语句的目的和业务逻辑
  • 说明特殊处理的原因
  • 记录性能优化的考虑
  • 维护 SQL 语句的版本历史

测试和验证

  • 为 SQL 语句编写测试用例
  • 验证边界情况
  • 测试性能和并发情况
  • 检查执行计划:EXPLAIN PLAN FOR SELECT ...
  • 定期审查和优化 SQL 语句

版本兼容性

语法兼容性

  • 避免使用特定版本的语法特性
  • 使用标准 SQL 语法
  • 检查函数的可用性
  • 测试在不同版本的 Oracle 上的执行情况
  • 记录版本特定的代码

性能差异

  • 了解不同版本的优化器行为
  • 调整 SQL 语句以适应不同版本
  • 测试不同版本的性能表现
  • 考虑版本特定的性能特性
  • 为不同版本制定不同的优化策略

常见问题(FAQ)

Q1: 如何提高 SQL 语句的可读性?

A1: 提高 SQL 语句的可读性可以通过以下方法:

  • 遵循一致的格式规范,包括缩进、换行和大小写
  • 使用有意义的表名和列名
  • 添加清晰的注释
  • 分解复杂 SQL 语句为多个步骤
  • 使用 WITH 子句提高复杂查询的可读性
  • 合理使用空格和空行分隔不同的逻辑部分

Q2: 如何避免 SQL 注入攻击?

A2: 避免 SQL 注入攻击可以通过以下方法:

  • 使用绑定变量:SELECT * FROM employees WHERE employee_id = :emp_id;
  • 避免拼接 SQL 语句
  • 对用户输入进行验证和过滤
  • 使用存储过程处理复杂操作
  • 限制用户权限,遵循最小权限原则
  • 使用应用程序框架的参数化查询功能

Q3: 如何优化复杂的连接查询?

A3: 优化复杂的连接查询可以通过以下方法:

  • 合理选择连接类型:INNER JOIN, LEFT JOIN, RIGHT JOIN
  • 小表驱动大表,减少连接操作的开销
  • 确保连接条件使用索引列
  • 避免笛卡尔积,确保连接条件完整
  • 使用 ANSI 标准连接语法
  • 考虑使用 HASH JOINMERGE JOIN 提高性能
  • 限制返回的列和行,只选择需要的数据

Q4: 如何处理 NULL 值?

A4: 处理 NULL 值可以通过以下方法:

  • 使用 NVL 函数:SELECT NVL(salary, 0) FROM employees;
  • 使用 COALESCE 函数处理多个可能的 NULL 值:SELECT COALESCE(salary, commission_pct, 0) FROM employees;
  • 使用 NULLIF 函数避免除以零错误:SELECT salary / NULLIF(commission_pct, 0) FROM employees;
  • 使用 IS NULLIS NOT NULL 检查 NULL 值
  • 考虑使用默认值约束,减少 NULL 值的使用
  • 避免在索引列中使用 NULL 值,可能影响索引效果

Q5: 如何编写可维护的 SQL 语句?

A5: 编写可维护的 SQL 语句可以通过以下方法:

  • 遵循一致的命名和格式规范
  • 添加清晰的注释,说明 SQL 语句的目的和逻辑
  • 分解复杂 SQL 语句为多个步骤
  • 使用视图简化复杂查询
  • 合理使用存储过程和函数
  • 模块化设计,避免重复代码
  • 编写测试用例验证 SQL 语句的正确性
  • 定期审查和优化 SQL 语句
  • 维护 SQL 语句的版本历史和变更记录