【问题标题】:TSQL: Trigger on CommitTSQL:提交时触发
【发布时间】:2012-12-15 17:57:51
【问题描述】:

我们有一个后台系统,它通过 MSDTC 存储过程将发票信息插入 SQL 数据库,应用程序插入标题,然后是详细信息。

我在标题表上设置了一个CLR 触发器,当插入记录时触发。

我遇到的问题是触发器在COMMIT TRANSACTION 之前触发,这意味着可能不会填充详细信息,这是触发的进程所必需的。此外,如果系统触发ROLLBACK TRANSACTION,则触发器已经触发。

我知道触发器不能分配给COMMIT,但想知道是否有人有其他想法。

我偶然发现了一个针对 oracle 的建议解决方案,您可以在其中创建一个更新 ON COMMIT 的 Materlised 视图,并尝试找到 TSQL 等效的索引视图,但没有成功实现它。

总结:
是否可以触发COMMIT TRANSACTION可能使用索引视图


CLR触发码

向队列发送 JMS 消息,由 Sonic ESB 处理。

[Microsoft.SqlServer.Server.SqlTrigger(Name = "InvoiceTrigger", Target = "Table", Event = "FOR INSERT")]
public static void InvoiceTrigger()
{
    //Declare Connection vairables
    string connectionURL, connectionDomain, connectionUser, connectionPassword, connectionQueue;
    //Constant
    connectionUser = "user";
    connectionPassword = "pass";
    connectionQueue = "Queue";
    //Local Environment
    connectionURL = "tcp://IP:2506";
    connectionDomain = "Domain1";

    //Create connection sonic domain
    SonicSend send = new SonicSend(connectionURL, connectionDomain, connectionUser, connectionPassword, connectionQueue);
    
    //Send Test message to pipe
    SqlCommand command;
    SqlTriggerContext triggContext = SqlContext.TriggerContext;
    SqlPipe pipe = SqlContext.Pipe;
    SqlDataReader reader;
    switch (triggContext.TriggerAction)
    {
        case TriggerAction.Insert:
            // Retrieve the connection that the trigger is using
            using (SqlConnection connection = new SqlConnection(@"context connection=true"))
            {
                connection.Open();
                command = new SqlCommand(@"SELECT LSH_LINKCODE, DOC_CODE, LSH_DOCNUM FROM INSERTED;", connection);
                reader = command.ExecuteReader();
                if (reader.HasRows)
                {
                    string xml;
                    char cr = (char)13;
                    int i = 0;
                    while (reader.Read())
                    {
                        
                        xml = @"<Invoice action='insert'>";
                        xml += "<LinkCode>" + reader.GetString(0).ToString() + "</LinkCode>";
                        xml += "<DocumentCode>" + reader.GetString(1).ToString() + "</DocumentCode>";
                        xml += "<DocumentNumber>" + reader.GetString(2).ToString() + "</DocumentNumber>";
                        xml += @"</Invoice>";
                        i++;
                        send.testJMSsend(xml);
                        
                    }
                   
                }

                reader.Close();
            }
            break;
    }

}

【问题讨论】:

  • 你为什么不把触发器中的代码放在你的事务中呢?
  • 在这种情况下,您需要重新考虑您的代码。在触发导致触发器的插入/更新之前,您需要拥有所有信息(可能在保存表中)。您没有发布任何代码,因此很难提供帮助。并且回滚也会回滚触发器在事务期间所做的任何更改。
  • 触发器由操作触发 - INSERTUPDATEDELETE。所以不-您不能将触发器“分配”给COMMIT-您需要将其分配给这些操作之一(或它们的组合)
  • 添加CLR代码,回滚的问题是C#已经执行了。

标签: sql sql-server tsql esb


【解决方案1】:

在有用的 cmets 指出不可能在触发器中使用提交之后。

我查看了由触发器启动的 ESB 流程,该流程现在使用传递的信息查询数据,这解决了我的问题,因为 BEGIN TRANSACTION 在查询的数据上创建了一个锁' t 在有COMMIT TRANSACTION 之前返回结果,这意味着该过程在查询返回数据之前不会继续,因此将始终填充发票详细信息。

此外,如果有 ROLLBACK TRANSACTION,该进程将超时并按预期抛出错误。

【讨论】:

    【解决方案2】:

    请参阅这篇文章,您可能必须使用 context_info,然后为这些记录触发触发器...

    Is there a way to disable a SQL Server trigger for just a particular scope of execution?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      • 2017-01-20
      • 2021-07-07
      • 2011-03-24
      相关资源
      最近更新 更多