情境:
每次在表格中插入/更新/删除数据时,最多需要做3件事:
Table1.Name
也应该更新{{1 }}到相同的值)不得更改数据库的体系结构和架构,并且必须使用触发器来完成要求。
问题
哪个选项更好?:
Table2.Name
(“D”表示删除)。每个操作的多个触发器被关注隔离。它们可以命名为:
D_TableName
- 用于从D_TableName_Logging
D_TableName_RI
我更喜欢选项2,因为单个代码单元只有一个问题。我不是DBA,对SQL Server足够了解,让我很危险。
是否有任何令人信服的理由来处理单个触发器中的所有问题?
答案 0 :(得分:4)
您说不得更改数据库的体系结构和架构。但是,通过创建触发器,您至少可以更改数据库的模式,并且可以认为是架构。
我可能会使用选项#1并创建额外的存储过程和UDF来处理日志记录,BL和RI,以便代码不会在各个触发器之间重复(触发器会调用这些存储过程和/或UDF) 。我真的不喜欢用你在方案2中提出的方式来命名触发器。
顺便说一句,请告诉贵组织的某人,这是疯了。 RI不应通过触发器强制执行,业务逻辑不属于数据库。答案 1 :(得分:2)
在一个触发器中执行所有操作可能会更有效,因为您可能最终会对(未编入索引的)inserted
和deleted
表执行更少的操作。
此外,当您有多个触发器时,可以设置触发的第一个和最后一个触发器,但是任何其他触发器将以任意顺序触发,因此如果您对特定触发器具有多于3个触发器,则无法确定性地控制事件序列动作。
如果这些考虑因素都不适用,那么这只是一个偏好问题。
当然,毫无疑问,使用触发器执行此操作的规范很糟糕。
答案 2 :(得分:2)
我同意@RandyMinder。但是,我会更进一步。触发器不是解决这种情况的正确方法。您描述的逻辑对于触发机制而言过于复杂。
您应该在存储过程中包装插入/更新/删除。这些存储过程可以管理业务逻辑和日志记录等。此外,他们明确了解正在发生的事情。调用存储过程的一系列存储过程是显式的。调用触发器的触发器链由insert / update / delete语句确定,这些语句不会显式调用触发器。
触发器的问题在于它们在不同的表中引入依赖关系和锁定,并且解开依赖关系可能是一场噩梦。同样,当问题可能位于触发器调用触发器调用存储过程调用触发器时,确定性能瓶颈可能是一场噩梦。
答案 3 :(得分:0)
如果您正在使用Microsoft SQL Server并且您能够修改执行DML语句的代码,则可以使用OUTPUT clause将更新的,插入的,已删除的值转储到临时表或内存变量中,而不是触发。这将使性能损失降至最低。