SQL CLR触发器 - 获取目标/表名称

时间:2011-09-27 04:57:18

标签: triggers sqlclr

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


SQL CLR触发器:

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

目的:

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

的信息:

可以将相同的CLR触发器绑定到多个表。

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

问题在于在Trigger中调用表名/触发器名称标识。 我尝试了所有DMV对象,到目前为止还没有任何解决问题的方法。顺便说一下,无法访问@@ PROCID。

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

2 个答案:

答案 0 :(得分:0)

提示是将触发目标设置为正确的级别。虽然它不是特定于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个\工具\ BINN \模式\ SQLSERVER \ 2006年\ 11个\事件

答案 1 :(得分:0)

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); 
                }
            }
        }
    }