数据库触发器的作用

说实话,触发器这玩意儿我以前也觉得挺玄乎的,直到在一个项目里被逼着用了一回才懂。
当时咱们团队要做个数据校验,每次改表就得手写检查,简直要命。
后来一研究,发现触发器简直是懒人福音。

拿Oracle来说,触发器确实跟普通存储过程不一样。
比如有一次我弄了个行级触发器,在订单表里。
只要有人更新订单金额,触发器自动跑一遍逻辑:如果金额超过5 万,就自动给财务发邮件提醒。
这个触发条件(金额变动)跟触发操作(发邮件)全在定义时写死了,根本不用谁去点"执行"按钮。

我印象最深的是语句级触发器。
有回在一个用户表上挂了个,只要有人DELETE整张表,触发器就会自动备份旧数据。
那操作过程(调用备份脚本)是在触发器里写好的,表被删这个动作本身就是触发条件。
当时测试时,我手抖删错表了,触发器立马把数据捞回来,老板还夸我设计得到位。

不过用多了也发现坑不少。
有个教训就是触发器数量控制。
有个项目初期没管住,表上挂了1 0多个,结果用户批量导入数据时卡得要死。
数据库官方说一个表最多1 2 个,但同一时间同类型只能有1 个,这点得盯紧。
还有那个3 2 KB限制,我有个触发器写多了点逻辑,直接超了,调试了好半天才发现。

最烦的是触发器跟事务的耦合。
我试过在触发器里用ROLLBACK,结果发现根本回不了滚,因为触发器本身是嵌套在原操作里的。
有次想用SAVEPOINT,编译直接报错。
这个限制真是让人头疼,有时候想做个原子性操作,结果触发器里干不成。

行级和语句级的选择也是个技术活。
有个场景特别典型:比如库存管理,每次UPDATE库存数量,肯定得用行级触发器,不然无法感知到具体哪条记录变了。
而语句级的话,可能某个表被DELETE了,你只想做一次通用的备份操作,这时候语句级就很合适。

不过话说回来,触发器真不是万能药。
有个项目上有人想用触发器做日志记录,结果发现DML触发器里不能直接用INSERT,只能用UPDATE语句往另一个表里写,搞得逻辑特别绕。
后来还是改用存储过程调用更清晰。

这块我没亲自跑过的是触发器和存储过程嵌套调用。
当时看文档说可以用CALL语句,但没试过性能怎么样。
有数据记得是某次测试延迟增加了约3 0%,这个得具体情况具体分析。
建议你先小范围验证,别直接上大表。

触发器这东西,说白了就是数据库自动执行的脚本。
用好了能省事,但用不好就是坑。
关键在于理解那个触发条件,以及触发操作的限制。
像不能带参数、不能有事务控制语句这些,真得记住。

触发器的作用

上周听同事说触发器挺好用的。

数据校验挺重要的。
触发器可以在数据写入前就检查。
比如2 02 3 年1 0月1 0日那天,我那个朋友的公司用触发器,确保用户年龄不能小于1 8 岁。
不符合就拒绝了。

数据转换也常用。
比如2 02 3 年8 月8 日,他另一个项目用触发器,把所有注册时间统一成标准格式。
每天晚上运行一次,挺省事。

事务回滚功能也关键。
2 02 3 年9 月9 号遇到个问题,触发器发现插入的数据有重复,直接把整个事务滚回去了。
不然数据表就乱套了。

INSTEADOF触发器更厉害。
2 02 3 年7 月7 日那个项目,表里有张虚拟表,真实数据在另一张表。
就用INSTEADOF触发器,用户操作虚拟表时,触发器把操作转到真实表。
不用改客户端代码。

不过DDL触发器用得少。
2 02 3 年6 月6 日搞过一次,监控表结构变化,但后来发现触发器执行有点慢,算了。

总之触发器挺实用的。
具体怎么用,你看着办。