数据库触发器是个坏主意吗?
根据我的经验,它们是邪恶的,因为它们可能导致令人惊讶的副作用,并且难以调试(特别是当一个触发器触发另一个触发器时).通常开发人员甚至不会考虑是否存在触发因素.
另一方面,似乎你必须FOO
在数据库中创建一个新的逻辑,然后在数据库中创建一个新的最简单的地方是FOO表上的插入触发器.
我们唯一一次使用触发器就是设置简单的东西ModifiedDate
.
触发器的主要问题是:a)它们完全是全局的 - 无论表活动的上下文如何,它们都适用; 和b)他们是隐秘的; 很容易忘记他们在那里,直到他们以无意的(并且非常神秘的)后果伤害你.
这意味着他们需要在适当的情况下小心使用; 根据我的经验,这仅限于关系完整性问题(有时候粒度比你声明性的更细); 通常不用于商业或交易目的.因人而异.
不,他们实际上是个好主意.如果您的特定触发器出现问题,那么您没有正确执行它们,但这通常意味着您的实现存在问题,而不是触发器本身的概念:-).
我们使用触发器很多,因为它将DBMS特定的活动置于它所属的数据库的控制之下.DBMS的用户不应该担心这类东西.数据的完整性取决于数据库本身,而不是使用它的应用程序或用户.如果数据库中没有约束和触发器以及其他功能,则由应用程序执行规则,并且只需要一个流氓或错误的应用程序/用户来销毁数据.
例如,在没有触发器的情况下,自动生成的列等奇妙的东西将不存在,并且您在选择它们时必须在每一行上处理一个函数.这可能会破坏DBMS性能,在插入/更新时创建自动生成的列要好得多,因为这是唯一一次更改.
此外,缺少触发器会阻止在DBMS上强制执行数据规则,例如预触发,以确保列具有特定格式.请注意,这与数据完整性规则不同,后者通常只是外键查找.
工具永远不是邪恶的.这些工具的应用可能是邪恶的.
我同意.触发器的问题是人,而不是触发器.虽然更多的是要考虑,更多地考虑并增加编码人员正确检查事物的责任,但我们不会丢弃索引以使我们的生活更简单.(错误的索引可能和坏的触发器一样糟糕)
触发器(在我看来)的重要性在于......
- 任何系统都应该始终处于有效状态
- 强制执行此有效状态的代码应该是集中的(不是每个SP都写入)
从维护的角度来看,触发器对于竞争对手的编码器非常有用,对于更多初级/业余的编码器来说也是如此.然而,这些人需要以某种方式学习和成长.
我想这取决于你的工作环境.你有可靠的人,他们学得很好,可以信任有条不紊吗?如果不是你,你似乎有两个选择:
- 接受你必须失去功能来补偿
- 接受你需要不同的人或更好的培训和管理
它们听起来很刺耳,我想它们都是.但这是基本的事实,在我看来......
我认为触发器不仅不是邪恶的,而且是良好的数据库设计所必需的.应用程序员认为数据库只受其应用程序的影响.他们经常是错的.如果要保持数据完整性,无论数据发生在何处,触发器都是必需的,并且避免它们是愚蠢的,因为一些程序员过于种族中心,不能认为除了他们珍贵的应用程序之外的其他东西可能会影响事物.如果您是一位称职的数据库开发人员,那么设计或测试或排除触发器故障并不困难.如果触发器发生意外结果(如果它对我来说那样),那么也很难确定触发器是否会导致意外结果.如果我得到一个错误,说我在sp中没有引用的表有一个FK错误,我知道甚至没有想到触发器导致问题,所以任何有能力的数据库开发人员也应如此.仅将业务规则放在应用程序中是我发现坏数据的首要原因,因为其他人不知道规则甚至存在并且在其进程中违反规则.以数据为中心的规则属于数据库,触发器是实施更复杂的规则的关键.
大多数情况下,是的.
触发器的难点在于它"背后"; 维护应用程序的开发人员可能很容易意识到它并没有意识到并且进行了更改,这些更改会使事情变得棘手,甚
它创造了一层复杂性,只增加了维护工作.
通常可以使用存储过程/例程来执行相同的操作,而不是使用触发器,但是以清晰且可维护的方式 - 调用存储的例程意味着开发人员可以查看其源代码并查看确切的发生情况.
触发器非常强大且有用,在任何情况下触发器都是解决问题的最佳方案.
它们也是一个非常好的"黑客"工具.通常情况下,您无法立即控制代码和数据库.如果您必须等待2个月才能获得代码的下一个主要版本,但是您可以立即将修补程序应用于数据库,那么您可以在表上设置触发器以执行一些其他功能.然后,当代码发布可能时,您可以根据需要将此触发器替换为相同功能的编码版本.
在一天结束时,如果你不知道它在做什么,一切都是"邪恶的".决定触发器是因为有开发人员不了解它们与认为汽车是邪恶的是相同的,因为有些人无法开车......
触发器有其用途 - 记录/审计和维护"上次修改"日期是两个非常好的用途,在之前的回复中已经提到过.
然而,良好设计的核心原则之一是业务规则/业务逻辑/无论您想要什么,都应该集中在一个地方.将一些逻辑放入数据库(通过触发器或存储过程)和应用程序中的一些逻辑违反了该原则.在两个地方复制逻辑甚至更糟,因为它们总是彼此不同步.
还有一个已经提到的"最少惊喜原则"问题.
如果使用得当,触发器是一个很好的工具.特别适用于审计更改,填充汇总表等内容.
现在他们可能是"邪恶的",如果你最终陷入"触发地狱",一个触发器开启其他触发器.我曾经在COTS产品上工作过他们所谓的"弹性触发器".这些触发器存储在一个表中,因为每次执行时都会编译动态sql stings .编译的触发器会查找并查看该表是否有任何flex触发器运行,然后编译并运行"flex"触发器.从理论上讲,这听起来像是一个非常酷的想法,因为产品很容易定制,但实际情况是数据库因为必须做的所有编译而爆炸了很多...
所以,是的,如果你保持你正在做的事情,他们是伟大的.如果它像审计,总结,自动排序等非常简单,没有概率.请记住表的增长率以及触发器将如何影响性能.
在较高级别,触发器1有两个用例
1)使"自动化"的东西发生.在这种情况下,触发器会产生副作用,它们会以预期的方式更改数据,前提是(原始)操作符插入,更新或删除已执行并导致触发器触发.
这里的普遍共识是触发器确实是有害的.因为它们改变了INSERT,UPDATE或DELETE语句的众所周知的语义.更改这三个原始SQL运算符的语义会让其他开发人员感到困惑,这些开发人员将来需要处理数据库表,这些表在使用SQL原语操作时不再以预期的方式运行.
2)执行数据完整性规则,而不是我们可以声明性地处理的规则(使用CHECK,PRIMARY KEY,UNIQUE KEY和FOREIGN KEY).在此用例中,所有触发器都是QUERY(SELECT)数据,以验证是否允许INSERT/UPDATE/DELETE进行更改.就像声明性约束对我们来说一样.只有在这种情况下,我们(开发人员)已经对执法进行了编程.
对后一种用例使用触发器是无害的.
我在博客上写道:http://harmfultriggers.blogspot.com
我知道认为触发器的开发人员应该始终使用它是实现所需功能的最直接方式,而开发人员永远不会.这几乎就像两个阵营之间的教条.
但是我个人完全同意MarkR - 你可以(几乎)总是编写功能相当于触发器的代码,这些代码将更加明显,因此更易于维护.
不是邪恶的.他们实际上简化了类似的事
1.记录/审核记录甚至数据库模式的更改
您可以在ALTER TABLE上使用触发器来回滚生产环境中的更改.这应该可以防止任何意外的表修改.
2.跨多个数据库实现参照完整性(主/外键关系等)