【问题标题】:SQL CLR Trigger - get Target / Table nameSQL CLR 触发器 - 获取目标/表名
【发布时间】:2017-07-16 20:43:41
【问题描述】:

跟踪列更改 - 多个目标/表的单个 SQL CLR 触发器


SQL CLR 触发器:

有没有办法从 CLR 代码中获取目标/表名?

目的:

我正在构建一个通用 SQL CLR 触发器来跟踪多个表中的列更改。

信息:

同一个 CLR 触发器可以绑定到多个表。

只要 CLR 触发器绑定到表,无论在 CLR 触发器属性中指定什么目标/表,它都会在任何表上正常触发。这意味着我可以创建 1 个 CLR 触发器并将其用于所有需要更改跟踪的表。

问题是在Trigger内调用表名/触发器名识别。 我尝试了所有 DMV 对象,到目前为止没有任何解决问题的方法。顺便说一句,@@PROCID 在 CLR 中不可访问。

PS:我有一个解决方案,但不能被认为是好的和可靠的。

【问题讨论】:

    标签: triggers sqlclr


    【解决方案1】:

    提示是将触发目标设置为正确的级别。虽然它不是特定于 CLR 的,但可以在 MSDN here 中找到详细信息,但以下内容可能对您有用。

    [Microsoft.SqlServer.Server.SqlTrigger (Name="TriggerName", Target="database", Event="FOR UPDATE")]
    

    然后要弄清楚哪些表或字段发生了更改,请访问 SqlXml 变量中的 EventData。我创建了一个类似于以下的类,以结构化方式访问属性。

    using System.Data.SqlTypes;
    using System.Xml;
    using System.Xml.Serialization;
    
    namespace CLRSQLTrigger
    {
    
    public class SqlEventData
    {
        readonly XmlDocument document = new XmlDocument();
    
        public SqlEventData(SqlXml sqlXml)
        {
            if (sqlXml != SqlXml.Null)
            {
                document.LoadXml(sqlXml.Value);
            }
        }
        public string EventType
        {
            get { return document.GetElementsByTagName("EventType")[0].InnerText; }
        }
    }
    

    }

    通过转储触发事件时返回的 SqlXml 变量,给定操作接收到的值更容易解码。获得这些值后,您可以使用类似于上述 EventType 属性的语法或直接在代码中使用 GetElementsByTagName 方法。实际上有 100 多个事件,每个事件有 4-12 个字段,所以这部分取决于您。如果您是认真的,则可以使用不同组合的 XSD,但与调试方法相比,它可能会减慢您的速度。 XSD 路径将类似于

    C:\Program Files\Microsoft SQL 服务器\100\Tools\Binn\schemas\sqlserver\2006\11\events

    【讨论】:

    • code[Microsoft.SqlServer.Server.SqlTrigger (Name="TriggerName", Target="database", Event="FOR UPDATE")]code 不会使项目编译。 msdn.microsoft.com/en-us/library/ms189799.aspx 在语法部分中写道:DML 触发器接受表/视图名称,DDL 触发器接受数据库或所有服务器。
    • 您的示例代码在 Sql Server 中生成此错误:指定的事件类型在指定的目标对象上无效。
    【解决方案2】:
    public partial class Triggers
        {
            [SqlTrigger(Name = "TriggerName", Target = "TableName", Event = "FOR UPDATE")]
            public static void TriggerName ()
            {
                SqlTriggerContext triggerContext = SqlContext.TriggerContext;
    
                if (triggerContext.TriggerAction == TriggerAction.Update)
                {
    
                    SqlConnection connection = new SqlConnection("Context Connection=true");
                    SqlCommand command = new SqlCommand();
                    command.Connection = connection;
                    command.CommandText = "SELECT * FROM INSERTED,DELETED";
                    connection.Open();
                    SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
                    if (SqlContext.TriggerContext.IsUpdatedColumn(reader.GetOrdinal("State")))
                    {
                        reader.Read();
                        long MessageID = Convert.ToInt64(reader["MessageID"]);
                        int State = Convert.ToInt32(reader["State"]);
                        reader.Close();
    
                        if (State == 1)
                            FunctionName.SendMassage(MessageID); 
                    }
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-28
      • 2015-06-07
      • 2012-02-08
      • 2017-02-04
      • 1970-01-01
      相关资源
      最近更新 更多