代码之家  ›  专栏  ›  技术社区  ›  Al007

Oracle触发器给出未知错误

  •  0
  • Al007  · 技术社区  · 8 年前

        USE [DMS_TEST]
    GO
    
    IF EXISTS (SELECT object_name(id)  FROM sysobjects
       WHERE xtype ='TR' AND object_name(id) = N'TR_SALESSTATUS_CHANGE')   
       DROP TRIGGER [TR_SALESSTATUS_CHANGE]
    GO
    
    CREATE TRIGGER [TR_SALESSTATUS_CHANGE] ON [VM_SDetail] 
    FOR UPDATE 
    AS 
    BEGIN
            Set NoCount On
            UPDATE          [VM_SDetail] 
            SET             SALESSTATUS = 1 
            From            [VM_SDetail]
                            [VM_SDetail] 
            INNER JOIN      INSERTED 
            ON              [VM_SDetail].ID = INSERTED.ID 
            Where           (Not Inserted.ValueVal Is NULL AND  (Inserted.ValueVal <> '')) 
            AND             Inserted.SALESSTATUS = 0;
    End
    GO
    

    我将此触发器转换为Oracle:

    CREATE OR REPLACE TRIGGER TR_SALESSTATUS_CHANGE AFTER UPDATE
    ON DMS_TEST.VM_SDetail 
    FOR EACH ROW 
    BEGIN
            UPDATE          DMS_TEST.VM_SDetail 
            SET             SaleStatus = 1 
            From            DMS_TEST.VM_SDetail
            INNER JOIN      :NEW 
            ON              DMS_TEST.VM_SDetail.ID = :NEW.ID 
            Where           (Not :NEW.ValueVal Is NULL AND  (:NEW.ValueVal <> '')) 
           AND             :NEW.SalesStatus = 0;
    End;
    

    我收到此警告,触发器未按预期工作:

    Warning: TRIGGER created with compilation errors.
    

    我正在使用TOAD。 我已经试了两天了。我试图消除并简化触发器,但即使使用简单的更新命令,它也无法工作。 关于这个bug或任何可以给我更多错误消息或详细信息的工具有什么想法吗?

    谢谢

    2 回复  |  直到 8 年前
        1
  •  2
  •   Justin Cave    8 年前

    首先,如果在中键入“show errors” SQL*Plus ,您将得到实际错误。第二,你不能加入 :new 伪记录。这不是一张桌子。第三,您几乎肯定不想查询 VM_SDetail 行级触发器中的 .假设 id 是表的主键,我猜您只是想设置 :new.SaleStatus

    CREATE OR REPLACE TRIGGER TR_SALESSTATUS_CHANGE AFTER UPDATE
      ON DMS_TEST.VM_SDetail 
      FOR EACH ROW 
    BEGIN
      IF(    (Not :NEW.ValueVal Is NULL AND  (:NEW.ValueVal <> '')) 
         AND :NEW.SalesStatus = 0 )
      THEN
        :new.SalesStatus := 1;
      END IF;
    END;
    

    你也可以把 IF 中的语句 WHEN 子句,以使触发器不会实际触发,除非满足条件。那么触发器的主体就是 :new.SalesStatus := 1; 线

    我还应该指出,在Oracle中,空字符串相当于 NULL 所以没有必要检查 ValueVal 两者都是 NOT NULL 且不等于空字符串。这样说更有意义

    IF( :new.ValueVal IS NOT NULL and
        :new.SalesStatus = 0 )
    THEN
    
        2
  •  2
  •   Michael S.    8 年前

    用F9执行它(插入符号处的Execute/compile语句)。编辑器工具栏上最左侧的按钮具有绿色播放按钮。您使用F5作为脚本执行它。正如Justin Cave指出的那样,这需要SHOW ERRORS,但作为脚本执行应该保留给脚本执行(多于1条语句)或当您想要模拟SQL*Plus行为时。单语句执行、编译对象等最好使用F9完成。它会自动获取错误和其他许多事情。