插入表格后触发

时间:2014-01-21 19:31:54

标签: oracle plsql triggers

create or replace
trigger addpagamento
after insert on marcacoes_refeicoes
for each row
declare 
  nmarcacaoa number;
  ncartaoa number;
begin

  select nmarcacao into nmarcacaoa from marcacoes_refeicoes where rownum < (select count(*) from marcacoes_refeicoes);
  select ncartao into ncartaoa from marcacoes_refeicoes where rownum < (select count(*) from marcacoes_refeicoes);
  insert_pagamentos(nmarcacaoa, ncartaoa); --this is a procedure

  exception when others then
  raise_application_error(-20001, 'Error in Trigger!!!');

end addpagamento;

当我尝试将insert语句运行到表“marcacoes_refeicoes”时,此过程会出错:就像表正在变异

create or replace
procedure insert_pagamentos 
(nmarcacaoa in number, ncartaoa in number)
AS 
BEGIN
  insert into pagamentos (nmarcacao, datapagamento, ncartao) values (nmarcacaoa, sysdate, ncartaoa);
  commit;
END INSERT_PAGAMENTOS;

3 个答案:

答案 0 :(得分:1)

简短(过度简化)回答:

您无法修改更改表格的触发器中的表格。

答案很长:

http://www.oracle-base.com/articles/9i/mutating-table-exceptions.php有更深入的解释,包括如何解决问题的建议。

答案 1 :(得分:1)

你正在遇到变异表问题,因为你正在从同一个表中选择触发器,但你似乎想要做的事情没有意义。获取nmarcacaoancartaoa值的查询将返回no_data_foundtoo_many_rows错误,除非在插入之前表格中只有2行:

select nmarcacao from marcacoes_refeicoes
where rownum < (select count(*) from marcacoes_refeicoes);

将返回除一个之外的所有行;因为你没有订购,被排除的那个将是随机的。虽然状态在触发器中是不确定的,但是你实际上并不存在多少行,并且它无论如何也不会让你进行此查询。无论如何,您通常无法获得单一价值,而且您实际想要的价值并不明显。

我只能想象您正在尝试使用当前插入的行中的值,并将它们放入单独的付款(pagamentos)表中。如果是这样,有一个内置机制可以使用correlation names来执行此操作,这使您可以将新插入的行称为:new(默认情况下):

create or replace
trigger addpagamento
after insert on marcacoes_refeicoes
for each row
begin
  insert_pagamentos(:new.nmarcacaoa, :new.ncartaoa);
end addpagamento;

:new指的是当前行,因此:new.nmarcacaoa是要插入的nmarcacaoa。您不需要(也不能)从表本身获取该值。 (即使使用建议的自治pragma,这将是一个单独的事务,并且无法看到新插入和未提交的数据)。

或者你可以直接插入;不确定程序在这里添加了什么:

create or replace
trigger addpagamento
after insert on marcacoes_refeicoes
for each row
begin
  insert into pagamentos(nmarcacao, datapagamento, ncartao)
  values (:new.nmarcacaoa, sysdate, :new.ncartaoa);
end addpagamento;

我已经删除了异常处理程序,因为它所做的只是屏蔽了真正的错误,这是无用的。

答案 2 :(得分:0)

根据以下评论编辑此答案:

您可以使用PRAGMA AUTONOMOUS_TRANSACTION来消除错误,但不要使用它,因为它不会解决任何目的。

使用PRAGMA AUTONOMOUS_TRANSACTION:

create or replace
trigger addpagamento
after insert on marcacoes_refeicoes
for each row
declare 
  PRAGMA AUTONOMOUS_TRANSACTION;
  nmarcacaoa number;
  ncartaoa number;
begin

  select nmarcacao into nmarcacaoa from marcacoes_refeicoes where rownum < (select count(*) from marcacoes_refeicoes);
  select ncartao into ncartaoa from marcacoes_refeicoes where rownum < (select count(*) from marcacoes_refeicoes);
  insert_pagamentos(nmarcacaoa, ncartaoa); --this is a procedure

  exception when others then
  raise_application_error(-20001, 'Error in Trigger!!!');

end addpagamento;

但是在这种情况下,select count(*) from marcacoes_refeicoes会在当前插入表格后为您提供新的计数。