如何在sybase 12.0中禁用级联触发器?

时间:2014-02-12 07:47:43

标签: sql triggers sybase

我有一个特定表的2个触发器。第一个是INSERT(address_create_tr),第二个是UPDATE(address_update_tr)。 例如,插入触发器:

CREATE TRIGGER address_create_tr ON Address FOR INSERT AS
BEGIN 
    Update Address SET createdDate = getdate() FROM inserted WHERE Address.ID =inserted.ID 
END

更新触发器是相同的,除了它在UPDATE操作上触发并更新updatedDate列的事实。当我插入新的地址行时,我的问题就出现了。插入触发address_create_tr触发器并且它级联调用address_update_tr触发器(这对我来说是不合需要的行为)。这会在address_create_tr被触发时发生,它会更新特定行的createdDate字段,当它更新createdDate时,它会触发address_update_tr,因此也设置了updatedDate字段。所以实际问题:

如何在Sybase 12.0中禁用级联触发器?

谢谢

1 个答案:

答案 0 :(得分:1)

可以在服务器范围内禁用嵌套触发器:

sp_configure 'allow nested triggers', 0

但是,您可能希望在提出要求之前与您的DBA联系,可能会有一些应用程序影响阻止这种情况发生。

可以为多个事件编写触发器,在提供的示例中,可以将触发器写入触发器以进行插入和更新,如下所示:

CREATE TRIGGER address_create_tr ON Address FOR INSERT, UPDATE AS

DECLARE
    @mode       char(1)

BEGIN

    select
            @mode = 'I'

    select
            @mode = 'U'
       from
            deleted            

    -- Only called for inserts 
    Update Address SET createdDate = getdate() FROM inserted WHERE Address.ID =inserted.ID 
        and @mode = 'I'

    -- Only called for updates
    Update Address SET updatedDate = getdate() FROM inserted WHERE Address.ID =inserted.ID 
        and @mode = 'U'

END
go

是否为插入或更新调用触发器取决于已删除表中是否存在行。删除的表格包含"之前的图像"行,所以如果没有行,则为插入触发触发器。

第一次更新仅在@mode =' I'时调用,即插入,第二次更新。

可以进一步优化触发器以将功能组合到单个更新语句中,这将提高性能:

CREATE TRIGGER address_create_tr ON Address FOR INSERT, UPDATE AS

DECLARE
    @mode       char(1)

BEGIN

    select
            @mode = 'I'

    select
            @mode = 'U'
       from
            deleted            

    Update Address SET 
            createdDate = 
                case 
                    when @mode = 'I' then getdate() else inserted.createdDate
                end,
            updatedDate =
                case
                    when @mode = 'U' then getdate() else inserted.updatedDate
                end
        FROM 
            inserted 
        WHERE 
            Address.ID =inserted.ID 

END
go

我使用下面的表定义和DML来测试它:

create table Address (
    ID int, 
    line1 varchar(40), 
    createdDate datetime null, 
    updatedDate datetime null) 
go

insert into Address (ID, line1) values ( 1, 'First Insert') 
go
insert into Address (ID, line1) values ( 2, 'Second Insert') 
go
update Address set line1 = 'Updated address' where ID = 2
go

结果如下:

1> select * from Address
2> go
 ID          line1                                                          createdDate                     updatedDate                     
 ----------- ------------------------------------------ ------------------------------- ------------------------------- 
           1 First Insert                                           Feb 16 2015  7:35AM                            NULL 
           2 Updated address                                        Feb 16 2015  7:35AM             Feb 16 2015  7:35AM 

(2 rows affected)
1> 

在Linux上运行的Sybase ASE 15.7上测试。

1> select @@version
2> go
 ---------------------------------------------------------------------------------------------------------------------------
 Adaptive Server Enterprise/15.7.0/EBF 19495 SMP /P/x86_64/Enterprise Linux/ase157/2820/64-bit/FBO/Fri Sep 16 00:54:35 2011
(1 row affected)
1>