第二次更新后运行PL / SQL表级触发器

时间:2015-02-18 20:55:18

标签: sql plsql oracle11g

我有这个问题,这个触发器在更新其他表中的行后调用更新表的过程。问题是你必须将表STAVKARACUNA更新两次到表RACUN更新但它使用旧值。以下是两者的代码:

以下是程序代码:

create or replace PROCEDURE ukupnaCenaRacun (SIF IN VARCHAR2) AS
  SUMA float := 0;
  suma2 float := 0;
  Mesec NUMBER;
  popust float :=0.1;
BEGIN

  SELECT SUM(iznos) INTO SUMA
  FROM STAVKARACUNA
  WHERE SIF = SIFRARAC;

  SELECT SUM(vredrobe*pdv) INTO SUMA2
  FROM STAVKARACUNA
  WHERE SIF = SIFRARAC;

  SELECT EXTRACT (MONTH FROM DATUM) INTO Mesec FROM RACUN WHERE SIF=SIFRARAC;

  IF(Mesec = 1) THEN
  UPDATE RACUN
  SET PDVIZNOS = SUMA2, ukupnozanaplatu = suma*(1-popust)
  WHERE SIFRARAC=SIF;
  END IF;

  IF (MESEC != 1) THEN
  UPDATE RACUN
  SET PDVIZNOS = SUMA2, ukupnozanaplatu = suma
  WHERE SIFRARAC=SIF;
  END IF;
END;

这是一个触发器:

create or replace TRIGGER "UKUPNACENA_RACUN_UKUPNO" 
AFTER INSERT OR UPDATE OR DELETE OF CENA,KOL,PDV ON STAVKARACUNA
DECLARE 
  SIF VARCHAR2(20) := PACKAGE_STAVKARACUNA.SIFRARAC; 
BEGIN
  PACKAGE_STAVKARACUNA.ISKLJUCI_TRIGER('FORBID_UPDATING');
  ukupnaCenaRacun(SIF);
  PACKAGE_STAVKARACUNA.UKLJUCI_TRIGER('FORBID_UPDATING'); 
END;

问题是当更新表STAVKARACUNA时,表RACUN没有任何反应,但下次更新表STAVKARACUNA时,表RACUN中的数据会更新但是使用旧值。 非常感谢你。

1 个答案:

答案 0 :(得分:2)

您是否知道桌面上的事件触发器不应该直接访问该表?代码是里面的 DML事件。这张桌子正好在某些说法中被改变了。因此,回到同一个表的任何查询都可以尝试读取正在被更改的数据。它可以尝试读取在执行提交之前不完全存在的数据,或者现在是一个值,但是一旦执行提交,它将是不同的值。该表是变异

这适用于触发器调用的触发器之外的任何代码。因此ukupnaCenaRacun过程在触发器的上下文中执行。然而,它会在两个地方查询表STAVKARACUNA(可以放在一个查询中,但这里既不存在也不存在)。

由于您没有收到变异表错误,我只能假设在提交触发事件之后才进行更新,但是直到之后您才会看到结果稍后提交 - 就像提交第二次更新时一样。

这个解释实际上听起来很空洞,因为我一直认为触发器执行的所有活动都是作为一个事务的一部分提交或回滚的。但这就是你所描述的行动。

SIF似乎是包规范中定义的包变量。由于过程中的所有内容都会关闭该值并且触发器不会更改值,因此SUMASUMA2也可以定义为变量,每当{{{{{{ 1}}改变?