【问题标题】:How to create update trigger with some condition?如何在某些条件下创建更新触发器?
【发布时间】:2019-03-28 02:50:15
【问题描述】:

我想创建一个触发器来执行声明为 details 列的条件只能在放置后 3 天内更改

CREATE TRIGGER BEFORE UPDATE

CREATE TRIGGER INSTEAD OF UPDATE

我有OrderIdDetailsOrderDate

我该怎么做?可以帮忙吗

【问题讨论】:

标签: sql oracle oracle11g database-trigger


【解决方案1】:

这是一个例子。

首先,测试用例:

SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.

SQL> create table test
  2    (orderid   number primary key,
  3     details   varchar2(20),
  4     orderdate date
  5    );

Table created.

SQL> insert into test (orderid, details, orderdate)
  2    select 1, 'test 1', date '2018-10-15' from dual union all
  3    select 2, 'test 2', date '2018-10-22' from dual;

2 rows created.

SQL> select sysdate from dual;

SYSDATE
----------
23.10.2018

SQL> select * from test;

   ORDERID DETAILS              ORDERDATE
---------- -------------------- ----------
         1 test 1               15.10.2018
         2 test 2               22.10.2018

SQL>

触发器:

SQL> create or replace trigger trg_bu_test
  2    before update of details on test
  3    for each row
  4  begin
  5    if trunc(sysdate) - :new.orderdate > 3 then
  6       raise_application_error(-20001, 'More than 3 days have passed; update is not allowed');
  7    end if;
  8  end;
  9  /

Trigger created.

测试:

SQL> -- ID = 1 - 8 days have passed, no update is allowed
SQL> update test set details = 'xxx' where orderid = 1;
update test set details = 'xxx' where orderid = 1
       *
ERROR at line 1:
ORA-20001: More than 3 days have passed; update is not allowed
ORA-06512: at "SCOTT.TRG_BU_TEST", line 3
ORA-04088: error during execution of trigger 'SCOTT.TRG_BU_TEST'


SQL> -- ID = 2 - 1 day passed - update is allowed
SQL> update test set details = 'yyy' where orderid = 2;

1 row updated.

SQL>

附: INSTEAD OF 触发器(您在问题中提到)与视图一起使用;忘记他们(在这种情况下)。

【讨论】:

  • 一切都很完美,解释得通俗易懂,一步一步来,非常感谢
【解决方案2】:

尝试使用 AFTER 触发器

create or replace TRIGGER TR_details_update
AFTER UPDATE ON order_det
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW

BEGIN
    IF UPDATING THEN 
        IF  NVL(:OLD.Details, 'XXX')     <>   NVL(:NEW.Details, 'XXX') AND :OLD.OrderDate <= TRUNC(SYSDATE) - 3  THEN            
               update order_det
               set Details = :new.Details
               where Details = :old.Details 
               and OrderId = :old.OrderId;
        END IF;
    END IF;
        EXCEPTION
        WHEN OTHERS THEN
    RAISE_APPLICATION_ERROR (-20000,'Details must be changed within 3 days of order date');
END TR_details_update;

【讨论】:

  • 为什么是AFTER 触发器而不是BEFORE 触发器?
  • 你为什么要检查你是否在更新?在 after UPDATE 触发器中你还会做什么?你为什么在触发器内UPDATE?在您的代码中,您只需什么都不做。另外,您期望哪个例外?这应该是 ELSE 的一部分,而不是 EXCEPTION。
  • 我得到了变异错误..所以我改成 AFTER trigger ...我在块内进行了更新,但在我看到你的触发器后这是不必要的...谢谢
猜你喜欢
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多