TOM说过他希望三样东西不曾存在:触发器,自治事务,WHEN OTHERS
级联删除、级联修改,在设计良好的系统中是不存在的
即使有,那也是小概率事件,必须专门写一段脚本来解决,而不是作为常规功能存在
不得不用触发器,要么是原系统模块化做得不够好,要么是不允许改动原有的代码
当然有时候不是不允许,而是风险太大
每个触发器都是一个隐藏的存储过程。隐藏的代码对开发者很不友好
如果你正在看一段别人的程序,总觉得少了点什么,折腾半天原来还有些动作隐藏在触发器里!
顺藤摸瓜去找了触发器,发现里面对其他表有DML,又有其他隐藏代码,是不是头很大?
这种连锁触发增加了复杂性,很容易失控。起初我也做过这种东西,觉得系统布满了精巧的机关,很有成就感
后来才发现这对维护来说简直就是噩梦加陷阱
因为触发器是隐藏的,它不执行你也不知道。假如有个触发器编译失效,DML还是不声不响的照样成功了!存储过程就不会这样
触发器没有办法绕过。假如你有个产品正在跑,这时候需要补几条故障时间的历史数据,INSERT上的触发器有些动作是你不想要的
这就难办了。
触发器还有MUTATING TABLE问题。很多人一看这问题就上自治事务,殊不知这是个馊主意
自治事务使得你看到的数据都是旧的,因为主事务所作的修改还未提交
多行的DML会多次触发,产生一大堆小事务,很容易发生死锁
在批量操作、多次触发的情况下,触发器的效率低,因为它相当于每次都执行一段PL/SQL
往往可以把它转化为等价的几个SQL,效率提高很多
触发器是对某种事件发生时的响应,共有5种不同类型的事件可以挂载触发器代码
在触发器中所做的一切,都处于开发的盲点之中,这是个后患
TRIGGER里面的SQL会被重复软解析,PLSQL的游标缓存不起作用了
即使要用触发器,也要把里面的代码转移出来做成存储过程,然后在触发器里调用存储过程
如果是行级的触发器,更新哪行就在哪行触发;如果是语句级的,整个UPDATE只触发一次
UPDATE语句是隐式游标,和你自己用游标逐条更新的效果一样但性能更好
下面是DML触发器令人深恶痛绝的三个实际案例:
㈠
如果尝试到一个不熟悉的项目做一下维护,就会对这种情况深恶痛绝
曾经一次为了找一个BUG,花了两天时间
最后发现,另外一个不是很相干的表,上面建了一个触发器对相关的表进行了更新
而这个触发器上有个BUG
㈡
有次维护系统,程序基本都是写在FORM里面的。结果发现一执行就会莫名其妙的更改掉表的一个值
害的我只好一点点MARK,一段段的测试,最后发现是对表INSERT的时候会更改。是表的trigger做怪
㈢
最近俺查找一个问题, 总觉得是USER操作的问题导致, 查看 FORM 程式没有异样, 但是保存的数据就是不对
好不容易查到不知是谁在DB端增加了一个触发器, 害我好难找
USER提出问题时我没有实测, 只是检查前端FORM代码, 其中有关于USER提到问题的逻辑
所以我怎么也没有想到DB中谁又写了个新的逻辑来覆盖了FORM中的逻辑. 真是郁闷坏了....
如果 FORM 中没有那段逻辑, 我还会很自然的想到可能是 DB 中有触发器. 可偏偏 FORM 中有那段逻辑, 奶奶的
当然啦,DML触发器的存在必定有其存在的优点
使用触发器后可能带来的麻烦, 我想这应该作为开发人员在要写触发器的时候需要考虑的因素.并不应该作为摒弃触发器的原因
级联删除、级联修改,在设计良好的系统中是不存在的
即使有,那也是小概率事件,必须专门写一段脚本来解决,而不是作为常规功能存在
不得不用触发器,要么是原系统模块化做得不够好,要么是不允许改动原有的代码
当然有时候不是不允许,而是风险太大
每个触发器都是一个隐藏的存储过程。隐藏的代码对开发者很不友好
如果你正在看一段别人的程序,总觉得少了点什么,折腾半天原来还有些动作隐藏在触发器里!
顺藤摸瓜去找了触发器,发现里面对其他表有DML,又有其他隐藏代码,是不是头很大?
这种连锁触发增加了复杂性,很容易失控。起初我也做过这种东西,觉得系统布满了精巧的机关,很有成就感
后来才发现这对维护来说简直就是噩梦加陷阱
因为触发器是隐藏的,它不执行你也不知道。假如有个触发器编译失效,DML还是不声不响的照样成功了!存储过程就不会这样
触发器没有办法绕过。假如你有个产品正在跑,这时候需要补几条故障时间的历史数据,INSERT上的触发器有些动作是你不想要的
这就难办了。
触发器还有MUTATING TABLE问题。很多人一看这问题就上自治事务,殊不知这是个馊主意
自治事务使得你看到的数据都是旧的,因为主事务所作的修改还未提交
多行的DML会多次触发,产生一大堆小事务,很容易发生死锁
在批量操作、多次触发的情况下,触发器的效率低,因为它相当于每次都执行一段PL/SQL
往往可以把它转化为等价的几个SQL,效率提高很多
触发器是对某种事件发生时的响应,共有5种不同类型的事件可以挂载触发器代码
在触发器中所做的一切,都处于开发的盲点之中,这是个后患
TRIGGER里面的SQL会被重复软解析,PLSQL的游标缓存不起作用了
即使要用触发器,也要把里面的代码转移出来做成存储过程,然后在触发器里调用存储过程
如果是行级的触发器,更新哪行就在哪行触发;如果是语句级的,整个UPDATE只触发一次
UPDATE语句是隐式游标,和你自己用游标逐条更新的效果一样但性能更好
下面是DML触发器令人深恶痛绝的三个实际案例:
㈠
如果尝试到一个不熟悉的项目做一下维护,就会对这种情况深恶痛绝
曾经一次为了找一个BUG,花了两天时间
最后发现,另外一个不是很相干的表,上面建了一个触发器对相关的表进行了更新
而这个触发器上有个BUG
㈡
有次维护系统,程序基本都是写在FORM里面的。结果发现一执行就会莫名其妙的更改掉表的一个值
害的我只好一点点MARK,一段段的测试,最后发现是对表INSERT的时候会更改。是表的trigger做怪
㈢
最近俺查找一个问题, 总觉得是USER操作的问题导致, 查看 FORM 程式没有异样, 但是保存的数据就是不对
好不容易查到不知是谁在DB端增加了一个触发器, 害我好难找
USER提出问题时我没有实测, 只是检查前端FORM代码, 其中有关于USER提到问题的逻辑
所以我怎么也没有想到DB中谁又写了个新的逻辑来覆盖了FORM中的逻辑. 真是郁闷坏了....
如果 FORM 中没有那段逻辑, 我还会很自然的想到可能是 DB 中有触发器. 可偏偏 FORM 中有那段逻辑, 奶奶的
当然啦,DML触发器的存在必定有其存在的优点
使用触发器后可能带来的麻烦, 我想这应该作为开发人员在要写触发器的时候需要考虑的因素.并不应该作为摒弃触发器的原因