数据库触发器是邪恶的?
数据库触发器是一个坏主意?
根据我的经验他们是邪恶的,因为他们可能会导致令人惊讶的副作用,并且难以debugging(特别是当一个触发器触发另一个触发器时)。 通常开发者甚至不会考虑是否有触发器。
另一方面,似乎如果你有必须发生的逻辑加class在数据库中创build一个新的FOO
,那么最简单的地方是放在FOO表上的插入触发器。
我们使用触发器的唯一时间就是设置ModifiedDate
等非常简单的事情。
触发器的主要问题是:a)它们完全是全局的 – 它们适用于任何表活动的上下文; 和b)他们是隐身的; 很容易忘记他们在那里,直到他们以无意的(而且非常神秘的)后果来伤害你。
这只是意味着他们需要小心使用适当的情况; 在我的经验中,这只限于关系完整性问题(有时细化程度比您可以声明的更精细); 通常不用于商业或交易目的。 因人而异。
不,他们其实是个好主意。 如果你的特定触发器有问题,那么你没有做正确的,但这通常意味着你的实现有一个问题, 而不是触发器本身的概念:-)。
我们使用触发器很多,因为它将DBMS特定的活动置于所属数据库的控制之下。 DBMS的用户不应该担心这种东西。 数据的完整性在于数据库本身, 而不是应用程序或使用它的用户。 如果没有数据库中的约束和触发器以及其他function,应用程序只需要执行规则,只需要一个stream氓或错误的应用程序/用户来销毁数据。
例如,如果没有触发器,自动生成的列等奇妙的东西就不存在,select它们时,你必须在每一行上处理一个函数。 这很可能会导致DBMS性能下降,因为在插入/更新时创build自动生成的列,因为这是唯一一次更改。
另外,缺less触发器会阻止在DBMS中执行数据规则(如预触发器)以确保列具有特定的格式。 请注意,这与通常只是外键查找的数据完整性规则不同。
工具从来不是邪恶的。 这些工具的应用可能是邪恶的。
触发器似乎适用于审计日志logging。
我同意。 触发器的问题是人,而不是触发器。 尽pipe看起来更多,但是更多的是考虑并增加了对编码人员正确检查的责任,所以我们不放弃索引来简化我们的生活。 (坏索引可能和坏触发器一样糟糕)
触发器的重要性(在我看来)是…
– 任何系统应始终处于有效状态
– 执行此有效状态的代码应该集中(不是写在每个SP中)
从维护的angular度来看,触发器对于更多的初级/业余玩家来说是非常有用的。 然而,这些人需要学习和成长。
我想这归结于你的工作环境。 你有没有可靠的人学习好,可以信任有条不紊? 如果不是,你似乎有两个select:
– 接受你将不得不失去function来弥补
– 接受你需要不同的人或更好的培训和pipe理
他们听起来很刺耳,我想他们是。 但这是基本的事实,在我看来…
我认为触发器不仅不是邪恶的,而且对于良好的数据库devise也是必要的。 应用程序员认为数据库只受其应用程序的影响。 他们往往是错的。 如果要保持数据的完整性,不pipe数据是从哪里来的,触发器都是一个要求,而避免使用触发器是愚蠢的,因为一些程序员太过民族性,认为除了应用程序以外的东西可能会影响事物。 如果你是一个有能力的数据库开发人员,devise,testing或者诊断触发器并不难。 如果触发器发生在你身上(就像我这样做),那么也很难确定触发器是否会引起意想不到的结果。 如果我得到一个错误,说我没有在我的sp中引用的表有一个FK错误,我甚至知道没有想到触发器导致了问题,所以应该是任何有能力的数据库开发人员。 把业务规则放在应用程序中是导致我发现数据不好的首要原因,因为其他人不知道规则是否存在,并在其进程中违反规则。 以数据为中心的规则属于数据库,触发器是执行更复杂规则的关键。
大部分是的。
一个触发器的难点在于它会“背后”。 维护应用程序的开发人员可能很难意识到它在那里,并做出改变,甚至没有注意到的事情。
它创造了一个复杂的层面,只是增加了维护工作。
一般来说,存储过程/例程不是使用触发器,而是通过一个清晰可维护的方式来做同样的事情 – 调用存储的例程意味着开发人员可以查看它的源代码,看看发生了什么。
触发器是非常强大和有用的,有许多情况下触发器是问题的最佳解决scheme。
他们也是一个非常好的“黑客”工具。 通常情况下,你不能立即控制代码和数据库。 如果您必须等待2个月才能获得代码的下一个主要版本,那么您可以立即将修补程序应用于数据库,然后可以在表上添加触发器来执行一些附加function。 那么当代码发布的时候,如果需要的话,你可以用你的编码版本来replace这个触发器。
在一天结束的时候,如果你不知道自己在做什么,那么一切都是“邪恶的”。 决定触发是因为有开发人员不理解他们是一样的论证汽车是邪恶的,因为有些人不能驾驶…
触发器有其用途 – logging/审计和保持“最后修改”date是在以前的回复中提到的两个很好的用途。
然而,良好devise的核心原则之一就是业务规则/业务逻辑/任何你想称之为的应该集中在一个地方。 把一些数据库中的逻辑(通过触发器或存储过程)和一些在应用程序中违反了这个原则。 在这两个地方复制逻辑更糟,因为他们总是会失去同步。
也有已经提到的“最不吃惊的原则”问题。
使用正确的触发器是一个很好的工具。 尤其适用于审计更改,填充汇总表等。
现在,如果用一个触发器触发其他触发器,最终导致“触发地狱”,它们就会变成“邪恶”。 我曾经在一个COTS产品上做过他们所谓的“flex触发器”。 这些触发器被存储在一个表中,因为每次执行dynamicSQL时都会被编译。 编译的触发器会查找并查看该表是否有任何flex触发器运行,然后编译并运行“flex”触发器。 理论上这听起来像是一个非常酷的想法,因为产品很容易定制,但现实是数据库几乎爆炸,由于所有的编译它必须做…
所以是的,如果你保持你的观点,他们是很棒的。 如果审计,总结,自动sorting等非常简单的事情, 只要记住表格的增长率以及触发器如何影响性能。
我知道那些认为触发器应该始终被用来实现他们想要的function的最直接的方式的开发者,以及那些永远不会的开发者。 这几乎就像两个阵营之间的教条。
不过,我个人完全同意MarkR – 你可以(几乎)总是编写function相当于触发器的代码,这样会更明显,因此更容易维护。
不是邪恶。 他们实际上简化了像
1.logging/更改logging甚至数据库模式的logging/审计
您可以在ALTER TABLE上有一个触发器,用于回滚生产环境中的更改。 这应该防止任何意外的表格修改。
2.在多个数据库中join引用的缺陷(主要/外键关系等)
不,他们不是邪恶的 – 他们只是被误解了: – D
触发器有一个有效的用途,但往往作为复古黑客,最终使事情变得更糟。
如果你正在开发一个数据库作为应用程序的一部分,逻辑应该总是在代码或sprocs打电话。 触发器稍后会导致debugging痛苦。
如果您了解如何locking,死锁以及DB如何访问磁盘上的文件,那么以正确的方式使用触发器(例如审计或存档直接访问数据库)可能非常有价值。
他们绝对不是邪恶的。 在重构数据库模式时,我发现触发器很重要,同时重命名列或将列拆分成两列(反之亦然)(例如:名称/姓氏案例)并协助转换。
他们对审计也非常有用。
这个答案特别适用于SQL Server。 (尽pipe这也可能适用于其他的RDBMSs,我不知道,我宁愿把它作为答案在这里,但是这被当作是一个骗局)。
任何答案都没有提到的一个方面就是安全性。 因为默认情况下,触发器在用户的上下文中执行,执行导致触发器触发的语句会导致安全威胁,除非检查所有触发器。
BOL在“ pipe理触发器安全性 ”标题下给出的示例是创build包含代码的触发器的用户,该代码将授予GRANT CONTROL SERVER TO JohnDoe ;
为了升级自己的权限。
在高层次上,触发器1有两种使用情况
1)让东西“自动”发生。 在这种情况下,触发器会产生副作用,它们会以(原始)操作符插入,更新或删除已执行并导致触发器触发的方式更改数据。
这里的一般共识是触发器确实是有害的。 因为它们改变了INSERT,UPDATE或DELETE语句的众所周知的语义。 改变这三个原始SQL操作符的语义会咬其他开发人员,他们将来需要在你的数据库表上工作,当他们用SQL原语对它们进行操作时,不再以预期的方式工作。
2)强制执行数据完整性规则,而不是我们可以用声明(使用CHECK,PRIMARY KEY,UNIQUE KEY和FOREIGN KEY)处理的规则。 在这个用例中,所有的触发器都是QUERY(SELECT)数据来validation是否允许INSERT / UPDATE / DELETE所做的更改。 就像声明性约束对我们来说一样。 只有在这种情况下,我们(开发商)已经规划了执法。
为后者使用触发器是没有害的。
我在博客上: http : //harmfultriggers.blogspot.com
如果有副作用,这是一个devise问题。 在一些数据库系统中,没有其他可能性来设置自动增量字段,即主密钥ID字段。
我认为他们可能是邪恶的,但只有在发展中的任何事情上才是邪恶的。
虽然我对他们没有太多的经验,但是在最近的一个项目中,我确实有过这样的经历,这导致了我的结论。 我与他们的问题是他们可能会导致业务逻辑最终在两个位置,一个代码库和一个数据库。
我认为这与使用sprocs类似的论点。 你经常有开发人员擅长SQL将业务逻辑写入数据库,而不是那些不在其他地方的人将业务逻辑写入数据库。
所以我的经验法则是看你的项目结构是什么。 如果在数据库中存储业务逻辑似乎是可行的,那么触发器可能是有用的。
说他们是邪恶的是一个exageration,但他们可以导致网格。 当一个触发器的触发导致其他触发器发射时,它变得非常复杂。 假设他们很麻烦: http : //www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html
在Oracle中使用触发器进行业务逻辑比看起来多,因为多个并发问题。 在其他会话提交之前,您看不到其他更改。
事实上,经常触发被滥用。 其实在大多数情况下,你甚至不需要它们。 但是,这并不一定就是坏事。
触发器很有用的一个场景就是当你有一个你没有源代码的遗留应用程序,并且没有办法改变它。
触发器的想法不是邪恶的,限制触发器的嵌套是邪恶的。