在过去,我从未成为在数据库表上使用触发器的粉丝.对我来说,他们总是表现出一些将在数据库方面发生的"魔力",远离我对应用程序代码的控制.我还想限制数据库必须完成的工作量,因为它通常是一个共享资源,我总是认为触发器在高负载情况下会变得昂贵.
也就是说,我发现了几个使用触发器的实例(至少在我看来它们是有意义的).最近,我发现自己有时可能需要"绕过"触发器.我不得不寻找方法来做到这一点,我仍然感到内疚,我仍然认为更好的数据库设计可以减少对这种绕过的需求.不幸的是,这个数据库被多个应用程序使用,其中一些应用程序是由一个非常不合作的开发团队维护的,他们会对模式更改感到尖叫,所以我被困住了.
关于触发器的一般意见是什么?爱他们?讨厌他们?认为它们在某些情况下有用吗?是否认为需要绕过触发器意味着你"做错了"?
触发器通常使用不正确,引入错误,因此应该避免.永远不要设计触发器来执行跨越表中行的完整性约束检查(例如"dept的平均工资不能超过X)".
Oracle副总裁Tom Kyte表示他更愿意删除触发器作为Oracle数据库的一个特性,因为它们经常在bug中发挥作用.他知道这只是一个梦想,并且触发器仍然存在,但如果他可以从Oracle中移除触发器,他将(以及WHEN OTHERS子句和自治事务).
可以正确使用触发器吗?绝对.
问题是 - 在很多情况下它们没有被正确使用,我愿意放弃任何感知的好处,只是为了摆脱它们造成的滥用(和错误). - 汤姆基特
将数据库视为一个伟大的大对象 - 在每次调用之后,它应该处于逻辑上一致的状态.
数据库通过表公开自己,并且可以使用触发器保持表和行的一致性.保持它们一致的另一种方法是禁止直接访问表,只允许它通过存储过程和视图.
触发器的缺点是任何动作都可以调用它们; 这也是一种力量 - 没有人会因无能而搞砸系统的完整性.
作为对应点,仅允许通过存储过程和视图访问数据库仍允许后门访问权限.具有足够权限的用户不会破坏数据库完整性,所有其他用户都使用存储过程.
至于减少工作量:当数据库不必处理外部世界时,它们的效率非常高; 你甚至会惊讶于甚至过程切换会伤害性能.这是存储过程的另一个好处:而不是十几次调用数据库(以及所有相关的往返),只有一个.
在单个存储过程中查找内容很好,但是当出现问题时会发生什么?假设您有5个步骤,第一步失败,其他步骤会发生什么?你需要在那里添加一大堆逻辑来满足这种情况.一旦开始这样做,就会失去该场景中存储过程的好处.
业务逻辑必须在某个地方,并且在数据库的设计中嵌入了许多隐含的域规则 - 关系,约束等是试图通过说,例如,用户只能拥有一个密码来编写业务规则.鉴于您已经开始通过具有这些关系等将业务规则推送到数据库服务器上,您在哪里绘制线?数据库何时放弃对数据完整性的责任,并开始信任调用应用程序和数据库用户以使其正确无误?嵌入这些规则的存储过程可以将大量政治权力推到DBA手中.它归结为你的n层架构中将存在多少层; 如果有演示文稿,业务和数据层,业务和数据之间的分离在哪里?业务层添加了什么增值功能?您是否将数据库服务器上的业务层作为存储过程运行?
是的,我认为不得不绕过触发器意味着你"做错了"; 在这种情况下,触发器不适合您.