如何避免 PL/SQL 中的行级锁定

How avoid row-level locking in PL/SQL

我有一个 table 包含 3 列 eid、salary、newsal。

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

我使用了触发器:

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

我无法按照提示执行此触发器

Error report: ORA-04084: cannot change NEW values for this trigger type 04084. 00000 - "cannot change NEW values for this trigger type" *Cause: New trigger variables can only be changed in before row insert or update triggers. *Action: Change the trigger type or remove the variable reference.

我的table定义为:

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

您可以创建一个 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)
);

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

BEFORE

Specify BEFORE to cause the database to fire the trigger before executing the triggering event. For row triggers, the trigger is fired before each affected row is changed.

Restrictions on BEFORE Triggers BEFORE triggers are subject to the following restrictions:

  • You cannot specify a BEFORE trigger on a view or an object view.
  • You can write to the :NEW value but not to the :OLD value.

AFTER

Specify AFTER to cause the database to fire the trigger after executing the triggering event. For row triggers, the trigger is fired after each affected row is changed.

Restrictions on AFTER Triggers AFTER triggers are subject to the following restrictions:

  • You cannot specify an AFTER trigger on a view or an object view.
  • You cannot write either the :OLD or the :NEW value.