【问题标题】:Under what conditions would a Sybase trigger not be called?在什么情况下不会调用 Sybase 触发器?
【发布时间】:2011-06-16 19:51:17
【问题描述】:

我在 Sybase ASE 数据库中有几个触发器,它们在更新两个表时触发:Docs 和 Trans。

触发器的定义如下所示:

对于文档:

 CREATE TRIGGER dbo.Index_Change_Docs
 ON dbo.docs
 FOR INSERT,UPDATE AS

 IF UPDATE(DOCTYPE) OR UPDATE(BATCH_NO) OR UPDATE(SCANDATE) OR           
 UPDATE(PERIOD_START_DATE) OR UPDATE(PERIOD_END_DATE) 
 OR UPDATE(DISPATCH_ID) OR UPDATE(DISPATCH_NAME) OR UPDATE(CHECKNUM) OR    
 UPDATE(CHECKAMT)
 BEGIN
    INSERT INTO 
    DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE) 
    SELECT Inserted.DOCID, GETDATE(), "N" FROM Inserted

 END

对于翻译:

 CREATE TRIGGER dbo.Index_Change_Trans
 ON dbo.Trans
 FOR INSERT,UPDATE AS

 IF UPDATE(TRANSNUM) OR UPDATE(CONTRACT) OR UPDATE(FRANCHISE) OR UPDATE(SSN) OR      
 UPDATE(STATE_CODE) OR UPDATE(TRANSTYPE)
OR UPDATE(AGENCYNUM) OR UPDATE(LOCKBOXBATCHNUM) OR UPDATE(PRODUCTCODE) 
 BEGIN

    INSERT INTO 
    DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE)
    SELECT DOCID, GETDATE(), "N" FROM DOCS
    WHERE Transnum = (SELECT Inserted.TransNum from Inserted)
 END

这些触发器的行为似乎有所不同,具体取决于对这些表进行更新的方式。

在一种情况下,这些表通过两个存储过程(Insert_Docs_SP 和 Insert_Trans_SP)进行更新。发生这种情况时,每个触发器都会触发一次(一次用于 Docs,一次用于 Trans)并且一切都按预期工作。

在另一种情况下,这些表在 Sybase 事务中通过两次数据库更新进行更新。在这里,第一次更新是通过调用应用程序中的内联 SQL 完成的(触发 Trans 触发器)。第二次更新是通过存储过程 - Insert_Docs_SP 完成的,与另一种情况相同 - 它不会触发触发器。

也许我不理解交易的处理方式?

【问题讨论】:

    标签: sql stored-procedures triggers sap-ase


    【解决方案1】:

    在您的两个触发器中,如果某些列被更新,触发器只会插入到 docid_sync 表中。您确定存储过程正在更新触发器中的列之一吗?如果它是来自触发器调用的递归更新,也不会调用触发器,但这里似乎不是这种情况。

    另一种可能性是调用事务是否使用 set triggers off 命令禁用了触发器。我将首先确保存储过程正在更新触发器检查中的列之一。

    另一个问题:在您的错误情况下,同一行是在内联 SQL 和存储过程中更新两次,还是它们更新了两个不同的行?

    【讨论】:

    • 存储过程正在更新触发器中的列(我已经更新了上面与存储过程相关的问题。)在这两种情况下,存储过程都在插入新记录。
    • 如果您可以访问 dev/test 环境中的代码,请尝试仅运行 SP 并查看它是否会执行触发器。
    • 单独运行 SP 确实会执行触发器。
    【解决方案2】:

    我找到了答案——它是按执行顺序排列的。我认为其中一个触发器没有被触发——在这种情况下是 Index_Change_Trans 触发器——但实际上它是。但是,我没有看到结果,因为此触发器依赖于 Docs 表中的条目。

    INSERT INTO 
    DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE)
    SELECT DOCID, GETDATE(), "N" FROM DOCS
    WHERE Transnum = (SELECT Inserted.TransNum from Inserted)
    

    因此,在 Trans 表在 Docs 表之前更新的情况下,Trans 触发器的运行不会在 Docid_Sync 表中显示更新 - 因为此时 Docs 表中没有具有适当 Transnum 的条目价值。在这些情况下,Docid_Sync 表只有一个条目,即 Docs 触发器的结果。

    在其他情况下,首先更新 Docs 表,然后更新 Trans 表。在这些情况下,Docid_Sync 表有两个条目——一个是 Docs 触发器的结果,另一个是 Trans 触发器的结果。

    【讨论】:

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