数据库是否会引发恶

时间:2009-01-20 07:01:04

标签: sql triggers

数据库触发器是个坏主意吗?

根据我的经验,它们是邪恶的,因为它们可能导致令人惊讶的副作用,并且难以调试(特别是当一个触发器触发另一个触发器时)。通常开发人员甚至不会考虑是否存在触发因素。

另一方面,似乎你的逻辑必须在数据库中创建一个新的FOO,然后在FOO表上插入触发器就是最简单的放置触发器。

我们使用触发器的唯一时间是设置ModifiedDate

等非常简单的事情

21 个答案:

答案 0 :(得分:137)

触发器的主要问题是:a)它们完全是全局的 - 无论表活动的上下文如何,它们都适用;和b)他们是隐秘的;很容易忘记他们在那里直到他们因意外(并且非常神秘)的后果而伤害你。

这意味着他们需要在适当的情况下小心使用;根据我的经验,这仅限于关系完整性问题(有时候粒度比你声明性的更细);通常不用于商业或交易目的。 YMMV。

答案 1 :(得分:74)

不,他们实际上是个好主意。如果您的特定触发器出现问题,那么您没有正确执行它们,但这通常意味着您的实现存在问题,触发器本身的概念: - )。

我们使用触发器很多,因为它将DBMS特定的活动置于它所属的数据库的控制之下。 DBMS的用户不应该担心这类东西。数据的完整性取决于数据库本身,使用它的应用程序或用户。如果数据库中没有约束和触发器以及其他功能,则由应用程序执行规则,并且只需要一个流氓或错误的应用程序/用户来销毁数据。

例如,在没有触发器的情况下,自动生成的列等奇妙的东西将不存在,并且您在选择它们时必须在每一行上处理一个函数。这可能会破坏DBMS性能,在插入/更新时创建自动生成的列要好得多,因为这是唯一一次更改。

此外,缺少触发器会阻止在DBMS上强制执行数据规则,例如预触发,以确保列具有特定格式。请注意,这与数据完整性规则不同,后者通常只是外键查找。

答案 2 :(得分:45)

工具绝不是邪恶的。 这些工具的应用可能是邪恶的。

答案 3 :(得分:20)

触发器似乎适用于审计日志记录。

答案 4 :(得分:20)

我同意。触发器的问题是人,而不是触发器。虽然更多的是要考虑,更多考虑并增加编码人员正确检查事物的责任,但我们不会丢弃索引以使我们的生活更简单。 (错误的索引可能和错误的触发一样糟糕)

触发器(在我看来)的重要性在于...... - 任何系统应始终处于有效状态
- 强制执行此有效状态的代码应集中(不是每个SP都写入)

从维护的角度来看,触发器对于竞争对手的编码器非常有用,对于更多的初级/业余编码器来说也是如此。然而,这些人需要以某种方式学习和成长。

我想这取决于你的工作环境。你有可靠的人,他们学得很好,可以信任有条不紊吗?如果不是你,你似乎有两个选择:
- 接受你必须失去功能来补偿 - 接受您需要不同的人或更好的培训和管理

他们听起来很刺耳,我猜他们是。但在我看来,这是基本的事实......

答案 5 :(得分:17)

我认为触发器不仅不是邪恶的,而且是良好的数据库设计所必需的。应用程序员认为数据库只受其应用程序的影响。他们经常是错的。如果要保持数据完整性,无论数据发生的来源是什么,触发器都是必需的,并且避免它们是愚蠢的,因为一些程序员过于种族中心,不能认为除了他们珍贵的应用程序之外的其他东西可能会影响事物。如果您是一位称职的数据库开发人员,那么设计或测试或排除触发器故障并不困难。如果触发器发生意外结果(如果它对我来说那样),那么也很难确定触发器是否会导致意外结果。如果我得到一个错误,说我在sp中没有引用的表有一个FK错误,我知道甚至没有想到触发器导致问题,所以任何有能力的数据库开发人员也应如此。仅将业务规则放在应用程序中是我发现坏数据的首要原因,因为其他人不知道规则甚至存在并且在其进程中违反规则。以数据为中心的规则属于数据库,触发器是实施更复杂的规则的关键。

答案 6 :(得分:13)

大多数情况下,是的。

触发器的难点在于它“背后”;维护应用程序的开发人员可能很容易意识到它并没有意识到并且做出了改变,这些更改会使事情变得棘手,甚至没有注意到。

它创造了一层复杂性,只增加了维护工作。

不是使用触发器,而是使用存储过程/例程,通常可以做同样的事情,但是以清晰且可维护的方式 - 调用存储的例程意味着开发人员可以查看其源代码并查看确切的内容发生。

答案 7 :(得分:9)

触发器功能非常强大且非常有用,在任何情况下触发器都是问题的最佳解决方案。

它们也是一个非常好的“黑客”工具。通常情况下,您无法立即控制代码和数据库。如果您必须等待2个月才能获得代码的下一个主要版本,但是您可以立即将修补程序应用于数据库,那么您可以在表上设置触发器以执行一些其他功能。然后,当代码发布时,您可以根据需要将此触发器替换为相同功能的编码版本。

在一天结束时,如果你不知道它在做什么,一切都是“邪恶的”。决定触发器是因为有些开发人员不了解它们与认为汽车是邪恶的是相同的,因为有些人无法开车......

答案 8 :(得分:7)

触发器有其用途 - 记录/审核和维护“上次修改”日期是以前回复中提到的两个非常好的用途。

然而,优秀设计的核心原则之一是业务规则/业务逻辑/无论你想要什么,都应该集中在一个地方。将一些逻辑放入数据库(通过触发器或存储过程)和应用程序中的一些逻辑违反了该原则。在这两个地方复制逻辑更糟糕,因为它们总是会彼此不同步。

还有一个已经提到的“最少惊喜原则”问题。

答案 9 :(得分:6)

在较高级别,触发器1有两个用例

1)使“自动化”的东西发生。在这种情况下,触发器会产生副作用,它们会以给定(原始)操作符插入,更新或删除操作并导致触发器触发的方式更改数据。

这里的普遍共识是触发器确实是有害的。因为它们改变了INSERT,UPDATE或DELETE语句的众所周知的语义。更改这三个原始SQL运算符的语义将会阻碍其他开发人员,他们将来需要处理数据库表,这些表在使用SQL原语对其进行操作时不再以预期方式运行。

2)执行数据完整性规则,而不是我们可以声明性地处理的规则(使用CHECK,PRIMARY KEY,UNIQUE KEY和FOREIGN KEY)。在这个用例中,所有触发器都是QUERY(SELECT)数据,以验证是否允许INSERT / UPDATE / DELETE进行更改。就像声明性约束对我们来说一样。只有在这种情况下,我们(开发人员)才会对执法进行编制。

对后一种用例使用触发器无害。

我在http://harmfultriggers.blogspot.com

上写博客

答案 10 :(得分:6)

如果使用得当,触发器是一个很好的工具。特别适用于审计变更,填充汇总表等等。

现在他们可能是“邪恶的”,如果你最终陷入“触发地狱”,一个触发器启动其他触发器。我曾经在COTS产品上工作过他们所谓的“弹性触发器”。这些触发器存储在一个表中,因为动态sql stings是在每次执行时编译的。编译的触发器会查找并查看该表是否有任何flex触发器运行,然后编译并运行“flex”触发器。从理论上讲,这听起来真的很酷,因为产品很容易定制,但实际情况是数据库因为必须进行的所有编译而大大爆炸......

所以,是的,如果你保持你正在做的事情,他们是伟大的。如果它像审计,总结,自动排序等非常简单,没有概率。请记住表的增长率以及触发器将如何影响性能。

答案 11 :(得分:5)

不是邪恶的。它们实际上简化了

之类的东西

1.记录/审核记录甚至数据库模式的更改

您可以在ALTER TABLE上触发,以回滚生产环境中的更改。这可以防止任何意外的表格修改。


2.跨多个数据库实施参照完整性(主要/外键关系等)

答案 12 :(得分:5)

我知道认为触发器的开发人员应该始终使用它是实现所需功能的最直接方式,而开发人员永远不会。这几乎就像两个阵营之间的教条。

然而,我个人完全同意MarkR - 你可以(几乎)总是编写功能相当于触发器的代码,这些代码将更加明显,因此更易于维护。

答案 13 :(得分:4)

不,他们不是邪恶的 - 他们只是被误解了:-D

触发器有一个有效的用途,但往往作为最终使事情变得更糟的复古黑客。

如果您正在将DB作为应用程序的一部分进行开发,那么逻辑应始终位于代码或sprocs中进行调用。触发器稍后会导致调试痛苦。

如果您了解锁定,死锁以及DB如何访问磁盘上的文件,那么以正确的方式使用触发器(例如审核或归档直接数据库访问)可能非常有价值。

答案 14 :(得分:4)

他们绝对不是邪恶的。在重构数据库模式,重命名列,或将列拆分为两列或反之亦然(例如:名称/姓氏情况)并协助转换时,我发现了触发器。

它们对审计也非常有用。

答案 15 :(得分:4)

此答案特别适用于SQL Server。 (虽然它也可能适用于我不知道的其他RDBMS。我宁愿把它作为答案给出here,但这是作为一个骗局而关闭的。)

到目前为止,在任何答案中都没有提到的一个方面是安全性。因为,默认情况下,触发器在执行导致触发器触发的语句的用户的上下文中执行,这可能会导致安全威胁,除非审查所有触发器。

BOL在“Managing Trigger Security”标题下给出的示例是用户创建包含代码GRANT CONTROL SERVER TO JohnDoe ;的触发器,以便升级自己的权限。

答案 16 :(得分:3)

说它们是邪恶的是一种夸张但它们可以引起网状物。当一个触发器的触发导致其他触发器触发时,它变得非常复杂。让我们说它们很麻烦:http://www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html

由于多并发问题,在Oracle中使用触发器执行业务逻辑比看起来更难。在其他会话提交之前,您不会看到另一个会话中的更改。

答案 17 :(得分:3)

我认为他们可能是邪恶的,但只会像发展中的任何其他东西一样邪恶。

虽然我对他们并没有多少经验,但我在最近的一个项目中确实有这些经验,这使我得出了这个结论。我遇到的问题是它们可能导致业务逻辑最终出现在两个位置,即代码库数据库。

我认为它与使用sprocs类似。您通常会让那些非常擅长将SQL编写业务逻辑的开发人员编入数据库,而不是那些不会在其他地方编写业务逻辑的人。

所以我的经验法则是看项目的结构是什么。如果将业务逻辑存储在数据库中似乎是可行的,那么拥有触发器可能很有用。

答案 18 :(得分:3)

如果有副作用,那就是设计上的问题。 在某些数据库系统中,没有其他可能设置自动增量字段,即主键ID字段。

答案 19 :(得分:1)

实际上,触发器经常被滥用。实际上在大多数情况下你甚至不需要它们。但这并不一定会让他们变坏。

我想到的一个场景,其中触发器很有用,当你有一个遗留的应用程序时,你没有源代码而且没有办法改变它。

答案 20 :(得分:1)

触发器的想法不是邪恶的,限制触发器的嵌套是邪恶的。