【问题标题】:How avoid row-level locking in PL/SQL如何避免 PL/SQL 中的行级锁定
【发布时间】:2017-06-15 10:48:51
【问题描述】:

我有一个包含 3 列 eid、salary、newsal 的表格。

我已经为所有员工插入了 eid 和薪水。 现在,如果我更新任何员工的薪水,我想要一个触发器,该触发器直接将该员工的薪水增加 20% 并将其存储到 newsal 列中。

我使用了触发器:

create or replace trigger pp1
after update on empsal
for each row
BEGIN
:new.newsal := :old.sal*1.2;
END;

我不能按照它说的执行这个触发器

错误报告:ORA-04084:无法更改此触发器的新值 类型 04084. 00000 - “无法更改此触发器类型的新值” *原因:新的触发变量只能在前行更改 插入或更新触发器。 *操作:更改触发器类型或删除变量引用。

我的表定义为:

> create table empsal(empno varchar2(8),sal number,newsal number,primary
> key(empno));

【问题讨论】:

  • 您不能将触发器更改为before update 而不是after update,就像错误消息中所说的那样吗?如果您使用after update,那么您可能无法更新该值?

标签: sql oracle oracle-sqldeveloper


【解决方案1】:

这是因为AFTER-triggers 无法写入:new-values。请改用BEFORE-trigger。例如,授予this documentation on triggers(强调我的):

之前

指定 BEFORE 以使数据库在之前触发触发器 执行触发事件。对于行触发器,触发器被触发 在更改每个受影响的行之前。

BEFORE 触发器的限制 BEFORE 触发器受 以下限制:

  • 您不能在视图或对象视图上指定 BEFORE 触发器。
  • 您可以写入 :NEW 值,但不能写入 :OLD 值。

之后

指定 AFTER 以使数据库在之后触发触发器 执行触发事件。对于行触发器,触发器被触发 在每个受影响的行更改后。

对 AFTER 触发器的限制 AFTER 触发器受 以下限制:

  • 您不能在视图或对象视图上指定 AFTER 触发器。
  • 您不能写入 :OLD 或 :NEW 值。

【讨论】:

    【解决方案2】:

    您可以将BEFORE UPDATE 触发器创建为

    CREATE OR REPLACE TRIGGER test_trg
       BEFORE UPDATE
       ON empsal
       FOR EACH ROW
    BEGIN
       :NEW.newsal := :new.sal * 1.2;
    END;
    

    例如

    INSERT INTO empsal (empno, sal)
         VALUES (123, 120);
    

    UPDATE empsal
       SET sal = 130;
    
    
    +-------+-----+--------+
    | EMPNO | SAL | NEWSAL |
    +-------+-----+--------+
    |   123 | 130 |    156 |
    +-------+-----+--------+
    

    如果您使用的是Oracle 11g,请利用虚拟列的概念,因此请尝试

    CREATE TABLE empsal
    (
       empno    VARCHAR2 (8),
       sal      NUMBER,
       newsal   GENERATED ALWAYS AS (sal * 1.2) VIRTUAL,
       PRIMARY KEY (empno)
    );
    

    【讨论】:

    • 感谢您的回答!但是我想做的是当我将sal从120更新到130时,我希望操作发生在130上,所以newsal = 156
    • @captainn3mo 我已经更新了触发代码,试试你是否得到 156。如果正确,请采纳答案。
    猜你喜欢
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 2013-09-23
    相关资源
    最近更新 更多