【问题标题】:How to update/insert in specific column of table through trigger如何通过触发器更新/插入表的特定列
【发布时间】:2021-08-28 22:26:34
【问题描述】:

我在使用此触发器时遇到错误。我只是想在 upby 列中添加操作来执行什么操作,用于更新和删除我只需声明 dbms_output.put_line('updated');供测试用。更新和删除效果很好,但是当我插入记录时它给了我错误。

create or replace trigger modifiy_byy after insert or update or delete on family for each row
    declare
    pragma autonomous_transaction;
   begin
        if inserting then
       insert into family(F_NUM,F_NAME,F_AGE,UPBY) 
                 values(:new.f_num,:new.f_name,:new.f_age,'insert');
        elsif updating then
                 dbms_output.put_line('updated');
       elsif deleting then
                 dbms_output.put_line('deleted');
    end if;
      end;
      /
     
      insert into family(f_num,f_name,f_age) values(5,'abv',10);
I am getting error like this:
ERROR at line 1:
ORA-00036: maximum number of recursive SQL levels (50) exceeded
ORA-06512: at "SYSTEM.MODIFIY_BYY", line 5
ORA-04088: error during execution of trigger 'SYSTEM.MODIFIY_BYY'
ORA-06512: at "SYSTEM.MODIFIY_BYY", line 5
ORA-04088: error during execution of trigger 'SYSTEM.MODIFIY_BYY'
ORA-06512: at "SYSTEM.MODIFIY_BYY", line 5

帮助我如何解决它: 提前谢谢你:)

【问题讨论】:

  • 您想在当前插入的行中将 UPBY 的值设置为“插入”吗?上面的代码会插入一个额外的行,这不是一回事。

标签: sql database oracle plsql triggers


【解决方案1】:

我先解释一下这个错误的原因:

当您在插入时创建了触发器,然后再次在触发器中插入时,触发器内的插入语句将再次调用触发器,这将一直持续到达到 50 的递归限制。这是系统抛出错误ORA-00036的时候。

处理变异触发器有一定的限制,即您可以使用您使用过的自治事务,但您只能从表中读取而不是写入,即不允许插入/更新或其他选项是使用语句级触发器而不是行水平触发。

以下是来自 O'Reilly 书籍的参考

以下是关于变异表的一些指导原则 错误: • 通常,行级触发器可能无法读取或写入 被解雇的表。该限制仅适用于 但是,行级触发器。语句级触发器对两者都是免费的 读取和修改触发表;这一事实为我们提供了一种方法 避免变异表错误。 • 如果您将触发器设为 自治事务(通过添加 PRAGMA AUTONOMOUS TRANSACTION 语句并在触发器的主体内提交),然后你 就能查询到射击表的内容。然而,你 仍然不允许修改表格的内容。

来到解决方案方面:

我不明白您为什么要在同一张表中插入完全相同的记录(只需添加 UPBY 列)。您可以通过添加单独的日志表并将数据插入该表中或在原始插入时插入记录来保留日志,而不是使用触发器执行另一个 DML 操作,这在性能方面也是一种开销。

【讨论】:

  • 非常感谢先生。我是初学者,所以我正在努力学习这一切。
【解决方案2】:

错误的方法。表发生了变异(因为触发器更新了主事务正在修改的同一个表),因此您尝试通过将其声明为 autonomous transaction 来拯救自己,但随后插入导致触发器触发并更新触发触发器的表以此类推,直到您用完 资源

除此之外,您犯的另一个巨大错误:永远不要在SYSSYSTEM 架构中做任何事情。

ORA-04088: 执行触发器“SYSTEM.MODIFIY_BYY”时出错

别管他们,他们拥有数据库,并且 - 如果您做了不应该做的事情,您将破坏数据库。在其他架构中进行训练(例如 SCOTTHR,如果可用,或创建您自己的架构)。


回到您的问题:您不必直接update 表,只需使用伪记录(:new:old,以适合您所做的为准)。

For a sample table:

SQL> create table family
  2    (f_num      number,
  3     f_name     varchar2(20),
  4     f_age      number,
  5     upby       varchar2(20)
  6    );

Table created.

触发器看起来像这样:

SQL> create or replace trigger modify_byy
  2    before insert or update or delete on family
  3    for each row
  4  begin
  5    if inserting then
  6       :new.upby := 'insert';            --> note this
  7    elsif updating then
  8       :new.upby := 'update';            --> and this
  9    elsif deleting then
 10       dbms_output.put_line('deleted');
 11    end if;
 12  end;
 13  /

Trigger created.

测试:

SQL> set serveroutput on;
SQL> insert into family(f_num, f_name, f_age) values (1, 'Little', 10);

1 row created.

SQL> select * from family;

     F_NUM F_NAME                    F_AGE UPBY
---------- -------------------- ---------- --------------------
         1 Little                       10 insert

SQL> update family set f_age = 20 where f_num = 1;

1 row updated.

SQL> select * from family;

     F_NUM F_NAME                    F_AGE UPBY
---------- -------------------- ---------- --------------------
         1 Little                       20 update

SQL> delete from family where f_num = 1;
deleted

1 row deleted.

SQL>

但是,触发器名称(以及 upby 列名称)表明触发器实际上应该记录 做了最后一次更改。如果是这样,它将被简化为

SQL> create or replace trigger modify_byy
  2    before insert or update on family
  3    for each row
  4  begin
  5    :new.upby := user;
  6  end;
  7  /

Trigger created.

SQL> insert into family(f_num, f_name, f_age) values (2, 'Foot', 30);

1 row created.

SQL> select * from family;

     F_NUM F_NAME                    F_AGE UPBY
---------- -------------------- ---------- --------------------
         2 Foot                         30 SCOTT

SQL>

在这种情况下处理删除没有多大意义;你必须有一个单独的“日志”表来记录删除。而且,当你这样做时,也切换插入和更新它(我的意思是日志表)。并添加一个时间戳列。

【讨论】:

  • 非常感谢先生。 :)
  • 先生,我的触发程序又有一个小问题。那么我可以亲自将我的代码发送给您吗?还是我在这里发帖?
  • 您可以编辑原始问题,也可以提出新问题
猜你喜欢
  • 2014-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-07
  • 2015-11-06
  • 2020-08-29
  • 2010-10-18
  • 1970-01-01
相关资源
最近更新 更多