PL/SQL 新人注意事项、常见错误与面试问题¶
本章作为 PL/SQL 教程的收官章节,不再新增语法,而是系统总结:
- 新人最容易踩的坑
- 项目中最常见、最危险的错误
- 面试中 真正会被问到、并区分水平的题目
这一章的目标只有一个:
👉 让新人少犯错、让面试回答“像做过项目的人”。
1. 新人最容易混淆的核心认知¶
1.1 把 PL/SQL 当成“增强版 SQL”¶
❌ 错误认知:
SQL 不够强,所以用 PL/SQL 来补
✅ 正确认知:
- SQL:集合运算、数据处理
- PL/SQL:流程控制、组织 SQL
📌 原则:
能用一条 SQL 解决的,绝不用 PL/SQL 循环
1.2 忽视 SQL 与 PL/SQL 的上下文切换¶
❌ 常见写法:
for r in (select * from big_table) loop
update big_table set ... where id = r.id;
end loop;
问题:
- 性能极差
✅ 正确方向:
- BULK COLLECT + FORALL
2. 新人高频致命错误(项目级)¶
2.1 吞异常(最危险)¶
❌ 错误示例:
exception
when others then
null;
后果:
- 错误被隐藏
- 数据不一致
- 无法排查生产事故
✅ 正确原则:
- 已知异常明确处理
- 未知异常必须抛出
2.2 错误的 COMMIT 位置¶
❌ 错误示例:
for i in 1..1000 loop
update ...;
commit;
end loop;
问题:
- 性能差
- 数据难以回滚
✅ 正确做法:
- 批量处理后统一 COMMIT
- 或 LIMIT 分批 COMMIT
2.3 在在线事务中让 PL/SQL COMMIT¶
❌ 场景:
- Java + Spring 调用存储过程
- 存储过程内部 COMMIT
后果:
- Java 事务失效
- 数据出现“半成功”
✅ 原则:
在线事务中,COMMIT 永远由 Java 控制
2.4 NULL 判断错误¶
❌ 错误写法:
if v_val = null then
✅ 正确写法:
if v_val is null then
📌 延伸:
- SQL 是三值逻辑(TRUE / FALSE / UNKNOWN)
3. 性能相关的新人误区¶
3.1 认为 BULK 一定更快¶
❌ 误区:
BULK COLLECT 一定比游标快
✅ 实际情况:
- 小数据量:游标更简单
- 大数据量:BULK 明显更快
📌 关键在于:
数据量 + 内存 + 业务复杂度
3.2 忽视 LIMIT¶
❌ 错误示例:
select * bulk collect into v_rows from huge_table;
风险:
- PGA 内存爆炸
✅ 正确做法:
- BULK + LIMIT 分批
4. PACKAGE 使用方面的常见问题¶
4.1 不用 PACKAGE,过程到处散落¶
问题:
- 无命名空间
- 权限难控
- 维护困难
✅ 项目原则:
核心业务逻辑必须封装在 PACKAGE 中
4.2 在 PACKAGE SPEC 中暴露太多东西¶
❌ 错误做法:
- 把所有过程都写进 SPEC
✅ 正确做法:
- SPEC 只暴露接口
- BODY 隐藏实现
5. 批处理相关常见错误¶
5.1 批处理不能重跑¶
❌ 问题设计:
- 无状态字段
- 无批次号
后果:
- 一旦失败只能手工修数据
✅ 正确设计:
- 状态控制
- 幂等设计
5.2 没有日志表¶
❌ 只用 dbms_output
问题:
- 生产环境不可见
✅ 必须:
- 日志表 + 自治事务
6. 面试高频问题(带答题思路)¶
Q1:PL/SQL 中游标和 BULK COLLECT 的区别?¶
答题思路:
- SQL 执行方式一样
- 区别在数据返回方式
- 上下文切换次数不同
Q2:存储过程里能不能 COMMIT?¶
答题思路:
- 在线事务不允许
- 批处理允许
- 触发器不允许
Q3:为什么项目中要用 PACKAGE?¶
答题思路:
- 接口与实现分离
- 权限控制
- 性能
Q4:批处理失败了怎么办?¶
答题思路:
- 支持重跑
- 日志定位
- 幂等设计
Q5:如何避免 PL/SQL 性能问题?¶
关键词:
- 减少上下文切换
- BULK / FORALL
- 合理 COMMIT
7. 新人到熟练工程师的关键转变¶
| 阶段 | 特点 |
|---|---|
| 新人 | 会写语法 |
| 熟练 | 知道风险 |
| 高级 | 能提前规避 |
8. 全书总结(一句话)¶
PL/SQL 不是写得多,而是写得稳、跑得久、不出事。
9. 本章 & 全教程结语¶
如果你能完整理解并实践:
- PACKAGE
- 异常设计
- 批量处理
- 事务边界
那么你已经:
✅ 不是“只会写 PL/SQL 的新人”,
而是 能在真实项目中承担责任的工程师。