【问题标题】:SQL Server 2008 MERGE statement - how to disable INSTEAD OF INSERT trigger to allow the MERGESQL Server 2008 MERGE 语句 - 如何禁用 INSTEAD OF INSERT 触发器以允许 MERGE
【发布时间】:2011-02-02 01:40:07
【问题描述】:

我正在尝试在存储过程中使用 SQL SERVER 2008 MERGE 语句来更新/插入表。 我在桌子上有一个INSTEAD OF INSERT 触发器,在尝试CREATE 过程时收到以下错误消息

MERGE 语句的目标“电话”在某些设备上具有 INSTEAD OF 触发器, 但不是全部,在 MERGE 语句中指定的操作。在 MERGE 语句中,如果任何操作在目标上启用了 INSTEAD OF 触发器,则所有操作都必须启用 INSTEAD OF 触发器。

我绝对不需要INSTEAD OF UPDATE 触发器,(由于表上启用了 CASCADE DELETES,因此无法创建)。

所以在存储过程中,我首先在MERGE 之前发出DISABLE TRIGGER 命令。但是当我运行存储过程时,我得到了同样的错误,好像DISABLE TRIGGER 命令永远不会运行。

【问题讨论】:

    标签: sql sql-server sql-server-2008 triggers merge


    【解决方案1】:

    查询优化器对您的 T-SQL 批处理进行静态解析,一旦看到 MERGE 语句,它就会验证需求。它不会考虑影响 MERGE 语句之前的触发器的任何 DDL 语句。

    您可以使用 GO 将语句分成单独的批次来解决此问题,但如果它在单个 SP(没有 GO 语句)中,您有两个选择

    • 将 MERGE 放入主调用的支持 SP;或
    • 使用动态 SQL

    动态 SQL

    让我们用触发器创建一个表

    create table tg1(i int)
    ;
    create trigger tg1_tg on tg1 instead of insert as 
    select 1
    GO
    

    然后尝试在表上合并

    alter table tg1 disable trigger tg1_tg
    ;
    merge tg1 as target
    using (select 1 union all select 3) as source (X) on target.i = source.x
    when matched then
        delete
    when not matched by target then
        insert (i) values (x)
    output $action, inserted.*, deleted.*
    ;
    alter table tg1 enable trigger tg1_tg
    ;
    

    不好……

    消息 5316,第 16 级,状态 1,第 1 行
    MERGE 语句的目标“tg1”在 MERGE 语句中指定的部分(但不是全部)操作上具有 INSTEAD OF 触发器。在 MERGE 语句中,如果任何操作在目标上启用了 INSTEAD OF 触发器,则所有操作都必须启用 INSTEAD OF 触发器。

    所以我们使用动态SQL

    alter table tg1 disable trigger tg1_tg
    ;
    exec ('
    merge tg1 as target
    using (select 1 union all select 3) as source (X) on target.i = source.x
    when matched then
        delete
    when not matched by target then
        insert (i) values (x)
    output $action, inserted.*, deleted.*
    ;')
    alter table tg1 enable trigger tg1_tg
    ;
    

    支持程序

    让我们创建一个执行 MERGE 的过程(生产过程可能会有一个表变量,使用 #temp 表或接受一些参数)

    create proc tg1_MERGE as
    merge tg1 as target
    using (select 1 union all select 3) as source (X) on target.i = source.x
    when matched then
        delete
    when not matched by target then
        insert (i) values (x)
    output $action, inserted.*, deleted.*
    ;
    GO
    

    不行……

    消息 5316,第 16 级,状态 1,第 1 行
    MERGE 语句的目标“tg1”在 MERGE 语句中指定的部分(但不是全部)操作上具有 INSTEAD OF 触发器。在 MERGE 语句中,如果任何操作在目标上启用了 INSTEAD OF 触发器,则所有操作都必须启用 INSTEAD OF 触发器。

    即使要创建它,您也需要禁用触发器 - 所以禁用触发器并再次创建 proc - 这次它会起作用。

    最后,你可以运行这个有效的批处理

    alter table tg1 disable trigger tg1_tg
    ;
    exec tg1_MERGE
    ;
    alter table tg1 enable trigger tg1_tg
    ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多