0

我必须使用触发器检查笔记的更新是否不低于 10%。如果它大于 10% 我必须将它调整为 10% 并写一条错误消息,如果新笔记低于 0 我必须将其设置为 0

当我尝试 raise_application 错误时,更新只是取消。并且我的订单选项 DBMS 不起作用更新以良好的价值完成但没有消息

CREATE OR REPLACE TRIGGER C3_update
BEFORE UPDATE OF note on Inscription
FOR EACH ROW
WHEN (NEW.note < OLD.note*0.9)
begin
    if(:NEW.note > 0) then
    :NEW.note := :OLD.note*0.9;
    dbms_output.enable;
    dbms_output.put_line ('la note ne peut descendre de plus de 10%');
    --or
    --RAISE_APPLICATION_ERROR(-20111,'the note can not be less than 10%');
    end if;

    if(:NEW.note < 0) then 
    :NEW.note := 0;
    RAISE_APPLICATION_ERROR(-20011,'the note can not be under 0');
    end if;
  end;
  /

我想设置注释并打印消息错误现在我只是取消更新或者我以良好的方式更新注释但消息不打印

4

1 回答 1

0

在我看来,这是一种错误的做法。业务规则不应由数据库触发器强制执行。如果我是你,我会把它放到前端应用程序中(输入新音符值的地方)。

这样做,您甚至可以通知用户正在发生的事情,并让他们决定是否要接受新值(您会根据这些条件建议)还是不接受(并且可能输入一个新值,有效值)。

正如您所注意到的,DBMS_OUTPUT.PUT_LINE它不起作用。如果您用来更新音符值的工具能够显示它,它会。(顺便说一句,您SET SERVEROUTPUT ON是吗?)例如,如果您使用的是 Oracle Forms,那么您什么也看不到

RAISE_APPLICATION_ERROR,当被调用时,结束子程序并返回用户定义的错误号和消息。但是,它也会使您所做的更新无效。即使您将触发器设置为自治事务,它也不起作用。例如:

SQL> drop table inscription;

Table dropped.

SQL> create table inscription (note number);

Table created.

SQL> insert into inscription (note) values (2);

1 row created.

SQL> create or replace trigger c3_update
  2    before update of note on inscription
  3    for each row
  4    when (new.note < old.note * 0.9)
  5  declare
  6    pragma autonomous_transaction;
  7    l_note inscription.note%type;
  8    l_info varchar2(100);
  9  begin
 10    if :new.note > 0 then
 11       :new.note := :old.note * 0.9;
 12       l_info := 'the note can not be less than 10%';
 13    elsif :new.note < 0 then
 14       :new.note := 0;
 15       l_info := 'the note can not be under 0';
 16    end if;
 17    -- Let's hope that COMMIT will save the updated value
 18    select note into l_note from inscription;
 19    dbms_output.put_line('Note before commit = ' || l_note);
 20    commit;
 21    select note into l_note from inscription;
 22    dbms_output.put_line('Note after commit = ' || l_note);
 23
 24    -- Raise the "error", hoping that it'll just display a message,
 25    -- but updated value will remain "as is"
 26    raise_application_error(-20001, l_info);
 27  end;
 28  /

Trigger created.

SQL> set serveroutput on
SQL> update inscription set note = -1;
Note before commit = 2
Note after commit = 2
update inscription set note = -1
       *
ERROR at line 1:
ORA-20001: the note can not be under 0
ORA-06512: at "SCOTT.C3_UPDATE", line 22
ORA-04088: error during execution of trigger 'SCOTT.C3_UPDATE'


SQL> select * from inscription;

      NOTE
----------
         2

看?note不是0,而是保持其原始值 ( 2)。它甚至从未得到值 0,因为触发器没有成功结束。如何检查?通过注释RAISE命令:

SQL> create or replace trigger c3_update
  2    before update of note on inscription
  3    for each row
  4    when (new.note < old.note * 0.9)
  5  declare
  6    pragma autonomous_transaction;
  7    l_note inscription.note%type;
  8    l_info varchar2(100);
  9  begin
 10    if :new.note > 0 then
 11       :new.note := :old.note * 0.9;
 12       l_info := 'the note can not be less than 10%';
 13    elsif :new.note < 0 then
 14       :new.note := 0;
 15       l_info := 'the note can not be under 0';
 16    end if;
 17    -- Let's hope that COMMIT will save the updated value
 18    select note into l_note from inscription;
 19    dbms_output.put_line('Note before commit = ' || l_note);
 20    commit;
 21    select note into l_note from inscription;
 22    dbms_output.put_line('Note after commit = ' || l_note);
 23
 24    -- Raise the "error", hoping that it'll just display a message,
 25    -- but updated value will remain "as is"
 26    --raise_application_error(-20001, l_info);
 27  end;
 28  /

Trigger created.

SQL> set serveroutput on
SQL> update inscription set note = -1;
Note before commit = 2
Note after commit = 2

1 row updated.

SQL> select * from inscription;

      NOTE
----------
         0

可以完成工作,但是 - 无法显示消息(我已经告诉过你原因)。

如果您打算将其包含UPDATE inscription set note = its_new_value到触发器本身中,请不要 - 您会遇到死锁,因为初始更新会触发执行更新的触发器,该触发器会调用执行更新等的触发器。

因此,据我所知,你不能做你想做的事,而不是触发器。

于 2019-04-06T20:35:22.187 回答