使用 :new 和 :old 在更新和插入之前触发 Oracle

Posted

技术标签:

【中文标题】使用 :new 和 :old 在更新和插入之前触发 Oracle【英文标题】:Oracle Trigger befor update and insert using :new and :old 【发布时间】:2021-12-30 11:21:38 【问题描述】:

我正在练习我在 PL/SQL 中学到的东西 我有一个“客户”表,其中包含:

客户(id、姓名、姓氏、电子邮件、城市、电话、佣金、薪水)

佣金应始终低于薪水

我被要求在插入和更新之前创建一个 oracle 触发器,以确保 commission 所以我做的是以下

 Create Trigger verifySalary
 Before insert, update
 ON Client
 for each row
 begin 
    if :new.salary < :new.comm then 
        raise_application_error(-20555, "commission should be lower than salary");
    end if  
 end

我不确定这是否正确,因为如果用户没有更新薪水和佣金或仅更新这两列之一,那么 :new.salary 和 :new 的值将是什么。佣金?

我应该如何进行? 提前谢谢你

【问题讨论】:

你可以通过对你的表使用检查约束来解决这个问题 当然,但我被要求使用触发器@MarEll 【参考方案1】:

您发布的触发代码无效。修复后(并应用了NVL 函数),它看起来像这样:

SQL> create table client (name varchar2(10), commision number, salary number);

Table created.

SQL> create or replace trigger verifysalary
  2    before insert or update on client
  3    for each row
  4  begin
  5    if nvl(:new.salary, 0) < nvl(:new.commision, 0) then
  6       raise_application_error(-20555, 'commision should be lower than salary');
  7    end if;
  8  end;
  9  /

Trigger created.

测试:

SQL> insert into client (name, commision, salary) values ('Little', 10, null);
insert into client (name, commision, salary) values ('Little', 10, null)
            *
ERROR at line 1:
ORA-20555: commision should be lower than salary
ORA-06512: at "SCOTT.VERIFYSALARY", line 3
ORA-04088: error during execution of trigger 'SCOTT.VERIFYSALARY'


SQL> insert into client (name, commision, salary) values ('Little', 10, 100);

1 row created.

SQL> update client set commision = 50;

1 row updated.

SQL> update client set commision = 500;
update client set commision = 500
       *
ERROR at line 1:
ORA-20555: commision should be lower than salary
ORA-06512: at "SCOTT.VERIFYSALARY", line 3
ORA-04088: error during execution of trigger 'SCOTT.VERIFYSALARY'


SQL> select * from client;

NAME        COMMISION     SALARY
---------- ---------- ----------
Little             50        100

SQL> update client set salary = null;
update client set salary = null
       *
ERROR at line 1:
ORA-20555: commision should be lower than salary
ORA-06512: at "SCOTT.VERIFYSALARY", line 3
ORA-04088: error during execution of trigger 'SCOTT.VERIFYSALARY'


SQL> update client set salary = 10;
update client set salary = 10
       *
ERROR at line 1:
ORA-20555: commision should be lower than salary
ORA-06512: at "SCOTT.VERIFYSALARY", line 3
ORA-04088: error during execution of trigger 'SCOTT.VERIFYSALARY'


SQL>

我觉得不错。

【讨论】:

由于 NVL 函数允许将空值替换为默认值,如果我使用 nvl(:new.salary, :old.salary ) 而不是 nvl(:new.salary, 0 ) 是否仍然正确? 不客气。从 NVL 功能开始:您最好的选择是尝试一下,看看会发生什么。您可能已经注意到,这一点也不难。

以上是关于使用 :new 和 :old 在更新和插入之前触发 Oracle的主要内容,如果未能解决你的问题,请参考以下文章

关于mysql中触发器old和new

MySQL AFTER 更新触发器与 New.col<> OLD.col

oracle new 和old 关键字

行级触发器和语句级触发器

新旧列中的触发器

ORA-04082: 表级触发器中不允许使用 NEW 或 OLD 引用