【问题标题】:How to write trigger on one table to prevent updating data but insert those data into other table如何在一个表上编写触发器以防止更新数据但将数据插入另一个表
【发布时间】:2021-10-12 15:23:06
【问题描述】:

我想停止将数据更新到我的 bb_tax 表中,并将这些数据存储到我的 tax_change_info 表中。我写了这个触发器。但是如果我提出错误,我的 tax_change_info 表中不会插入任何内容。它毫无例外地工作,但它会将数据更新到我不想要的 bb_tax 中。 我应该如何编写触发器来实现这一点?

这是我的触发器。

CREATE OR REPLACE TRIGGER CHECK_TAX_RATE
BEFORE UPDATE OF taxrate 
ON BB_TAX 
FOR EACH ROW  
DECLARE 
v_user varchar(50);

BEGIN 
    select user into v_user from dual;
    INSERT INTO TAX_CHANGE_INFO VALUES(v_user,:OLD.TAXRATE, :NEW.TAXRATE);
    dbms_output.put_line('insert done');
    
    RAISE_APPLICATION_ERROR(-20505,'You are not allowed to update taxes.');   
END;

【问题讨论】:

    标签: oracle plsql triggers


    【解决方案1】:

    当您引发异常然后操作失败时,您不能同时拥有两者。 BEFORE UPDATE 触发器没有任何 :NEW 值。

    如果你想阻止更新,那么你可以这样做:

    CREATE OR REPLACE TRIGGER CHECK_TAX_RATE
       AFTER UPDATE OF taxrate ON BB_TAX 
       FOR EACH ROW      
    BEGIN 
        -- no need for 'select user into v_user from dual;'
        INSERT INTO TAX_CHANGE_INFO VALUES(USER, :OLD.TAXRATE, :NEW.TAXRATE);
        :NEW.TAXRATE := :OLD.TAXRATE;
    END;
    

    【讨论】:

    • 谢谢你的回答。我试过了,但它为语句抛出错误:NEW.TAXRATE := :OLD.TAXRATE; “ORA-04084: 无法更改此触发器类型的新值”
    • 我在扳机前用过,休息时和你的一样,效果很好。非常感谢
    【解决方案2】:

    您的初始请求是捕获更改尝试并引发异常以让用户知道请求失败。接受的答案确实阻止了更新并捕获了更改尝试,但是(恕我直言)这是最糟糕的失败。它不会让用户认为请求的更改没有发生;从用户的角度来看,更新是成功的。之后使用税率的任何结果都不会产生预期的结果。
    现在确实不能直接通过触发器获得最初的预期结果。但是有一个解决方法。创建另一个过程以插入更改尝试。将此过程定义为 AUTONOMOUS_TRANSACTION。这允许您提交,但仍将其与主事务分开。触发器简单地调用这个过程,并在返回时抛出异常。见example here

    缺点:如果用户尝试更新多行,则上述仅捕获第一行,因为未处理后续行。要捕获所有尝试的更改,您可以使用复合触发器并在 AFTER STATEMENT 部分中引发异常。

    【讨论】:

    • 是的,你是对的。我认为它不会让用户知道数据实际上没有更新。
    猜你喜欢
    • 2013-12-05
    • 2015-03-21
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 2016-08-10
    • 2017-05-17
    • 2019-05-20
    • 1970-01-01
    相关资源
    最近更新 更多