繁体   English   中英

反对将数据插入其他表的 SQL 触发器的原因?

[英]Reasons for objection to SQL triggers that insert data into other tables?

我们公司的一个有一定权威的人告诉我,在数据库中创建触发器来更改另一个表中的行是一个“数据库禁忌”。

我已经使用这种技术来创建默认初始配置、自动维护审计日志以及在连接到该数据库的异构应用程序中始终如一地维护的各种其他事情。 十多年来,我一直认为这是一种集中关系约束维护并让与数据交互的应用程序承担责任的适当方式。

因此,我的 BS 仪表与此挂钩。 我是否遗漏了该技术的一些根本错误,使其成为一种不好的做法?

如果你对你的触发代码很小心,它本质上没有什么不好的。 有些人被错误的触发代码所困扰,然后认为触发器是错误的(尽管问题是错误的触发代码)。 然后他们将其概括为“从不使用触发器”。

另一个问题是......

以审计表为例,假设您有一个更新表并将数据放入审计表的存储过程。 现在假设您编写触发器代码将数据放入审计表。 您最终可能会得到重复的审计数据。

这是个人喜好。 不过,在我看来,这是不好的做法。 管理一个在表上具有更新其他表的触发器的数据库可能有点不守规矩,这会引发另一个触发器来更新另一个表,等等。

对我来说,将所有功能包装到存储过程中更有意义,这样所有逻辑都在一个地方。

不过,各有各的。

这可能是公司的政策,但不是绝对的禁忌。 除非您知道并控制数据库,否则这样做的问题是其他表的修改可能效率低下(这通常很难识别为问题),并且存在级联的危险 - 即修改此表触发另一个触发器,该触发器可能会更新另一个表....

因此,我不会将其称为“禁忌”,而是要谨慎行事。

我认为这类似于在结构化编程中避免goto语句的警告。 与将一堆 DML 放入触发器相比,你应该很难找到一个“更好”的答案,因为错误处理触发器很容易让你措手不及,但有时这是解决手头问题的最佳答案。

我的经验主要是在 SQL 服务器上。 旧版本没有更改跟踪或级联参照完整性,因此在过去糟糕的日子里,您可能不得不自己编写触发器来处理日志记录和参照完整性管理。 现在,平台中内置了用于这两种功能的高级工具。 它们比加载 DML 的触发器“更干净”,但仍然允许您保持这些功能集中。

即便如此,仍然存在在触发器中编写代码可以最好地完成工作的情况。 如果您通过分析得出结论认为触发器是您需要的工具,请不要让教条阻止您完成工作。

正如您所说,并非所有将行插入另一个表的触发器都是坏的,例如一个触发器而不是在 AUDIT 表中保留该行的先前版本。 但是在不知道细节的情况下,我确实怀疑您通过触发器创建的“默认初始配置”在存储过程中可能会更好,因为 SP 更具自我记录性。

应避免特殊的副作用——我所说的“特殊”是指一个人对绕过久经考验的标准做事方式的捷径的想法。 它们使持续的维护变得困难,并且对于后来发生的粗心的程序员来说可能是陷阱。

我仍在寻找定义“最佳实践”的那本书——我想我会在“数据库禁忌的大书”旁边找到它。

就个人而言,我鼓励团队尽可能避免触发因素。 我和他们有过不好的经历——我同意用锤子击打自己并不会使所有的锤子都变坏,但触发器更像是钉枪而不是锤子——伤害的机会肯定存在。

触发器是“副作用”——您的明确意图是在表中插入一条记录; 作为这种意图的副作用,发生了一大堆其他事情。 与我合作的大多数团队都没有“数据库专家”——开发人员跨多个层次工作,将所有副作用留在他们的大脑中是很费力的。 这为错误和性能问题创造了机会——不是因为某人愚蠢或懒惰,而是因为技术变得更加复杂。

有些问题最好(甚至只能)通过触发器解决——强制引用完整性是一个经典。 有些问题经常通过触发器来解决,这让我很紧张——尤其是当它们反映业务规则或使用审计表时。 有些问题 - 在我看来 - 太接近钉枪触发器而无法通过触发器来解决,例如商业领域的计算(例如计算销售税额)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM