0

对于一个简单的 sql-server 更新触发器,我可以写一个这样的类:

[Microsoft.SqlServer.Server.SqlTrigger (Name="MyTrigger", Target="[dbo].[MyTable]", Event="FOR UPDATE")]
public static void MyTrigger() { //... my code }

但是,如果我只想触发一列更新,那将是这样的:

create trigger myTrigger
on myTable
for update as
if update(MyColumn)
begin
    -- my code
end

我应该使用什么样的Microsoft.SqlServer.Server.SqlTrigger属性?

4

1 回答 1

1

可能这可以帮助你。

[Microsoft.SqlServer.Server.SqlTrigger (Name="Trigger1", Target="Table1", Event="FOR UPDATE")]
public static void Trigger1()
{
    SqlConnection conn = new SqlConnection("context connection=true;");
    SqlCommand cmd = new SqlCommand("select top 0 * from Table1", conn);

    conn.Open();

    SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SchemaOnly);

    if (SqlContext.TriggerContext.IsUpdatedColumn(dr.GetOrdinal("columnname")))
    {
        SqlContext.Pipe.Send("columnname was updated");
    }
    else
    {
        SqlContext.Pipe.Send("columnname was not updated");
    }

    dr.Close();
    conn.Close();
} 

您无法阻止有选择地运行触发器,无论更新列,它都会始终运行。但是,一旦启动,您可以查阅 COLUMNS_UPDATED() 函数:

返回一个 varbinary 位模式,指示表或视图中插入或更新的列。COLUMNS_UPDATED 用于 Transact-SQL INSERT 或 UPDATE 触发器主体内的任何位置,以测试触发器是否应执行某些操作。

因此,您可以根据更新的列调整触发逻辑以采取适当的行动。

话虽如此,从 SQLCLR 调用 WCF 是一个非常非常糟糕的主意。从触发器调用 WCF 更糟糕。您的服务器将在生产中死机,因为事务将阻止/中止等待某些 HTTP 响应爬回网络。更不用说您的调用在存在回滚的情况下本质上是不正确的,因为您无法撤消 HTTP 调用。执行此类操作的正确方法是通过队列将操作和 WCF 调用解耦。您可以使用用作队列的表来执行此操作,可以使用真正的队列,也可以使用更改跟踪。其中任何一个都允许您将更改和 WCF 调用分离,并允许您从单独的进程而不是 SQLCLR 进行调用

资料来源:CLR 触发器仅更新特定列

于 2012-05-24T10:12:49.440 回答