【问题标题】:SQL Server triggers - order of executionSQL Server 触发器 - 执行顺序
【发布时间】:2010-09-10 18:45:33
【问题描述】:

有谁知道 SQL Server 如何确定执行顺序触发器(相同类型,即在触发器之前)。有什么方法可以改变它,以便我可以指定我想要的顺序。如果没有,为什么不呢。

谢谢。

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql


    【解决方案1】:

    如果您正担心触发订单,那么您真的应该退后一步,考虑您正在尝试做什么以及是否有更好的方法来做到这一点。这不是一件容易改变的事情,这一事​​实应该告诉你一些事情。

    触发器看起来总是一个非常巧妙的解决方案,并且在正确的位置它们非常有价值,但是价格很高,而且很容易用它们制造调试噩梦。过去,我在尝试调试一些晦涩的数据库行为时浪费了很多时间,却发现原因隐藏在一个被忽视的触发器中。

    【讨论】:

      【解决方案2】:

      使用sp_Settriggerorder存储过程,可以定义触发器的执行顺序。

      sp_settriggerorder [ @triggername = ] ‘[ triggerschema. ] triggername’
      , [ @order = ] ‘value’
      , [ @stmttype = ] ’statement_type’
      [ , [ @namespace = ] { ‘DATABASE’ | ‘SERVER’ | NULL } ]
      

      第二个参数“order”可以取三个值,这意味着它最多可以考虑三个触发器。

      1. 首先 - 触发器首先被触发
      2. 最后 - 触发器最后触发
      3. 无 - 触发器按随机顺序触发。

      【讨论】:

        【解决方案3】:

        使用这个:

        例如:

        USE AdventureWorks;
        GO
        EXEC sys.sp_settriggerorder @triggername = N'', -- nvarchar(517)
            @order = '', -- varchar(10)
            @stmttype = '', -- varchar(50)
            @namespace = '' -- varchar(10)
        

        第一个和最后一个触发器必须是两个不同的触发器。

        First : 首先触发触发器。

        Last : 最后触发触发器。

        无:触发器以未定义的顺序触发。

        查看此链接以获取 @stmttype 的值:DDL Events

        对于@namespace = { 'DATABASE' | '服务器' | NULL } 更多信息请参见:DDL Triggers

        【讨论】:

          【解决方案4】:

          在这种情况下的百万​​美元声明 -

          sp_settriggerorder:指定最先触发的AFTER触发器 或最后。在第一个和最后一个之间触发的 AFTER 触发器 触发器以未定义的顺序执行。

          来源:MSDN

          【讨论】:

            【解决方案5】:

            使用 SetTriggerOrder 很好,但如果您的代码依赖于特定的执行顺序,为什么不将所有触发器包装到存储过程中,让第一个调用第二个,第二个调用第三个,等等。

            然后你只需在触发器中执行第一个。

            将来有人会感激他们不必在系统表中挖掘来确定自定义执行顺序。

            【讨论】:

            • 一般我们不这样做,因为我们无法轻松访问存储过程中的 Inserted 和 Deleted 伪表。
            • @mwigdahl 您应该实现一种设计模式,让您在 Sprocs 中运行所有业务逻辑 DML,而不是临时编写插入/更新/删除语句。在那里,您将可以访问要插入/更新的值,并且可以轻松查询您将要删除的数据。我不是 ORM 的粉丝,因为(作为 DB 纯粹主义者),我认为所有 DML 都应该封装在 Sprocs 中(修复除外)。如果你做不到(可能是第 3 方数据库,或者你是新人,没人会听关于在重新架构上投入时间),那么欢迎触发-H-E-double-hockysticks。
            【解决方案6】:

            您可以使用sp_settriggerorder 定义表上每个触发器的顺序。

            但是,我认为最好使用一个触发器来执行多项操作。这是特别是,所以如果顺序很重要,因为如果您有多个触发器,那么这种重要性不会很明显。想象一下有人试图在数月/数年内支持数据库。当然,在某些情况下,您可能需要多个触发器,或者它确实是更好的设计,但我会开始假设您应该拥有一个并从那里开始工作。

            【讨论】:

            • 如果执行顺序很重要,最好使用单个触发器,但如果不重要,情况就不是这样了。前任。 - 我有一个项目,桌子上有两个触发器。如果有人不使用提供的 SP 来更新表,其中之一会记录更改。另一个充当 3 个表之间的 FK,具有无法通过“内置”FK-s 描述的复杂关系。更新表的 SP 在工作时禁用日志触发器(以避免重复日志),但我仍然希望“键触发器”运行。如果执行顺序无关紧要,则按任务分组触发器以提高“代码可读性”。
            【解决方案7】:

            您可以使用 sp_settriggerorder 来保证先触发哪个触发器、最后触发哪个触发器以及中间触发哪个触发器。如果您需要同步三个以上,在 SQL Server 2005 中似乎是不可能的。

            这是来自here 的样本(链接的文章有更多信息)。

            sp_settriggerorder [ @triggername = ] ‘[ triggerschema. ] triggername’
            , [ @order = ] ‘value’
            , [ @stmttype = ] ’statement_type’
            [ , [ @namespace = ] { ‘DATABASE’ | ‘SERVER’ | NULL } ]
            

            【讨论】:

              【解决方案8】:

              sp_settriggerorder 仅适用于 AFTER 触发器。

              【讨论】:

                【解决方案9】:

                使用这个系统存储过程:

                sp_settriggerorder[@triggername = ] 'triggername', [@order = ] 'value', [@stmttype = ] 'statement_type'
                

                【讨论】:

                  【解决方案10】:

                  顺序由sql server设置,你唯一能做的就是使用系统sp(sp_settriggerorder)来设置哪个触发器先触发,哪个触发器最后触发。

                  除了将第一个和最后一个触发器设置为触发之外,您无法修改或告诉 sql server 将使用哪个顺序。因此,您将希望构建您的触发器,以便它们不依赖于它们被触发的顺序。即使你确定了他们今天开火的顺序,明天也可能会改变。

                  此信息基于 Sql Server 2000,但我不认为 2005/2008 在这方面的表现有所不同。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2014-11-12
                    • 1970-01-01
                    • 2018-03-18
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-11-26
                    • 2010-10-13
                    相关资源
                    最近更新 更多