简体   繁体   English

多个触发器与单个触发器

[英]Multiple triggers vs a single trigger

Scenario: 场景:

Each time data is inserted/updated/deleted into/in/from a table, up to 3 things need to happen: 每次在表格中插入/更新/删除数据时,最多需要做3件事:

  1. The data needs to be logged to a separate table 需要将数据记录到单独的表中
  2. Referencial integrity must be enforced on implicit related data (I'm referring to data that should be linked with a foreign key relationship, but isn't: eg. When a updating Table1.Name should also update Table2.Name to the same value) 必须对隐式相关数据强制执行引用完整性(我指的是应该与外键关系链接的数据,但不是:例如。当更新Table1.NameTable2.Name更新为相同的值)
  3. Arbitrary business logic needs to execute 任意业务逻辑需要执行

The architecture and schema of the database must not be changed and the requirements must be accomplished by using triggers. 不得更改数据库的体系结构和模式,并且必须使用触发器来完成要求。

Question

Which option is better?: 哪个选项更好?:

  1. A single trigger per operation (insert/update/delete) that handles multiple concerns (logs, enforces implicit referencial integrity, and executes arbitrary business logic). 每个操作(插入/更新/删除)的单个触发器,用于处理多个问题(日志,强制隐式参考完整性,并执行任意业务逻辑)。 This trigger could be named D_TableName ("D" for delete). 此触发器可以命名为D_TableName (“D”表示删除)。
  2. Multiple triggers per operation that were segregated by concern. 每个操作的多个触发器被关注隔离。 They could be named: 它们可以命名为:

    • D_TableName_Logging - for logging when something is deleted from D_TableName_Logging - 用于从中删除内容时的日志记录
    • D_TableName_RI
    • D_TableName_BL

I prefer option 2 because a single unit of code has a single concern. 我更喜欢选项2,因为单个代码单元只有一个问题。 I am not a DBA, and know enough about SQL Server to make me dangerous. 我不是DBA,对SQL Server足够了解让我变得危险。

Are there any compelling reasons to handle all of the concerns in a single trigger? 是否有任何令人信服的理由来处理单个触发器中的所有问题?

Wow, you are in a no-win situation. 哇,你是一个没有赢的局面。 Who ever requested that all this stuff be done via triggers should be shot and then fired. 谁曾要求通过触发器完成所有这些工作应该被拍摄然后被解雇。 Enforcing RI via triggers? 通过触发器执行RI?

You said the architecture and schema of the database must not be changed. 您说不得更改数据库的体系结构和架构。 However, by creating triggers, you are, at the very least, changing the schema of the database, and, it could be argued, the architecture. 但是,通过创建触发器,您至少可以更改数据库的模式,并且可以认为是架构。

I would probably go with option #1 and create additional stored procs and UDFs that take care of logging, BL and RI so that code is not duplicated amoung the individual triggers (the triggers would call these stored procs and/or UDFs). 我可能会使用选项#1并创建额外的存储过程和UDF来处理日志记录,BL和RI,以便代码不会在各个触发器中重复(触发器将调用这些存储过程和/或UDF)。 I really don't like naming the triggers they way you proposed in option 2. 我真的不喜欢用你在方案2中提出的方式来命名触发器。

BTW, please tell someone at your organization that this is insane. 顺便说一句,请告诉你组织的某个人,这是疯了。 RI should not be enforced via triggers and business logic DOES NOT belong in the database. RI不应通过触发器和业务逻辑强制执行,也不属于数据库。

Doing it all in one trigger might be more efficient in that you can possibly end up with fewer operations against the (un indexed) inserted and deleted tables. 在一个触发器中完成所有操作可能会更有效,因为您可能最终会对(未编入索引的)已inserteddeleted表执行更少的操作。

Also when you have multiple triggers it is possible to set the first and last one that fires but any others will fire in arbitrary order so you can't control the sequence of events deterministically if you have more than 3 triggers for a particular action. 此外,当您有多个触发器时,可以设置触发的第一个和最后一个触发器,但任何其他触发器将以任意顺序触发,因此如果您对特定操作具有多于3个触发器,则无法确定性地控制事件序列。

If neither of those considerations apply then it's just a matter of preference. 如果这些考虑因素都不适用,那么这只是一个偏好问题。

Of course it goes without saying that the specification to do this with triggers sucks. 当然,毫无疑问,使用触发器执行此操作的规范很糟糕。

I agree with @RandyMinder. 我同意@RandyMinder。 However, I would go one step further. 但是,我会更进一步。 Triggers are not the right way to approach this situation. 触发器不是解决这种情况的正确方法。 The logic that you describe is too complicated for the trigger mechanism. 您描述的逻辑对于触发机制来说太复杂了。

You should wrap inserts/updates/deletes in stored procedures. 您应该在存储过程中包装插入/更新/删除。 These stored procedures can manage the business logic and logging and so on. 这些存储过程可以管理业务逻辑和日志记录等。 Also, they make it obvious what is happening. 此外,他们明确了解正在发生的事情。 A chain of stored procedures calling stored procedures is explicit. 调用存储过程的一系列存储过程是显式的。 A chain of triggers calling triggers is determined by insert/update/delete statements that do not make the call to the trigger explicit. 调用触发器的触发器链由insert / update / delete语句确定,这些语句不会显式调用触发器。

The problem with triggers is that they introduce dependencies and locking among disparate tables, and it can be a nightmare to disentangle the dependencies. 触发器的问题在于它们在不同的表中引入依赖关系和锁定,并且解开依赖关系可能是一场噩梦。 Similarly, it can be a nightmare to determine performance bottlenecks when the problem may be located in a trigger calling a trigger calling a stored procedure calling a trigger. 同样,当问题可能位于触发器调用触发器调用存储过程调用触发器时,确定性能瓶颈可能是一场噩梦。

If you are using Microsoft SQL Server and you're able to modify the code performing the DML statements, you could use the OUTPUT clause to dump the updated, inserted, deleted values into temporary tables or memory variables instead of triggers. 如果您使用的是Microsoft SQL Server,并且能够修改执行DML语句的代码,则可以使用OUTPUT子句将更新的,插入的,已删除的值转储到临时表或内存变量而不是触发器中。 This will keep performance penalty to a minimum. 这将使性能损失降至最低。

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

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