包,触发器和程序无法正常工作

时间:2017-03-14 14:48:45

标签: database oracle plsql triggers procedure

我需要一些帮助,因为我不知道这段代码的问题在哪里。

我有2张桌子。产品(id,..,currentPrice)和价格(id,product_id,日期,价格)。我需要创建触发器和过程,当插入,更新或删除Price.price中的值时,这些触发器和过程将自动更新Products.currentPrice中的值。 我创建了一个包,两个触发器和一个过程,它们都编译好了但是当我插入,更新或删除一个值时没有任何反应。 但是,当我手动调用过程并插入product_id(例如,Products表中现有产品的值为1)时,每次都会更新Products.currentPrice中id为1的产品的值。 我猜BEFORE触发器的值没有保存在PACKAGE变量中,因为我没有找到数据'错误。 我正在使用SQL Developer和Oracle 11g XE。

这是我的代码:

CREATE OR REPLACE PACKAGE mypackage IS
gid NUMBER;
END;


CREATE OR REPLACE TRIGGER trg_currentprice1
BEFORE INSERT OR UPDATE OR DELETE ON prices
FOR EACH ROW
BEGIN
  IF (INSERTING OR UPDATING) THEN
    BEGIN
      mypackage.gid := :new.product_id;
    END;
  ELSE
    BEGIN
      mypackage.gid := :old.product_id;
    END;
  END IF;
END;


CREATE OR REPLACE TRIGGER trg_currentprice2
AFTER INSERT OR UPDATE OR DELETE ON prices
DECLARE
  v_id NUMBER := mypackage.gid;  
BEGIN
    calc_currentprice(v_id);
END;


CREATE OR REPLACE PROCEDURE calc_currentprice(prodid IN NUMBER) AS
  curprice Products.currentPrice%TYPE;
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  curprice := 0;
SELECT price INTO curprice FROM prices
WHERE product_id = prodid AND date = (SELECT MAX(date) FROM prices WHERE product_id = prodid AND date <= SYSDATE);
EXECUTE IMMEDIATE 'ALTER TRIGGER trg_products_forbid2 DISABLE';
UPDATE products
SET currentPrice = curprice
WHERE product_id = prodid;
EXECUTE IMMEDIATE 'ALTER TRIGGER trg_products_forbid2 ENABLE';
END;

1 个答案:

答案 0 :(得分:2)

你在做一些有关的事情。首先,您尝试使用两个触发器来执行一系列工作。触发器触发的顺序将无法保证。在一个触发器中考虑以下内容。

CREATE OR REPLACE TRIGGER trg_currentprice1
BEFORE INSERT OR UPDATE OR DELETE ON prices
FOR EACH ROW
BEGIN
  IF (INSERTING OR UPDATING) THEN
    BEGIN
      calc_currentprice(:new.product_id);
    END;
  ELSE
    BEGIN
      calc_currentprice(:old.product_id);
    END;
  END IF;
END;

其次,在你的proc中,你指定了一个自治事务,但是你没有提交。

现在,这些可以帮助你的代码,但还有一些你应该知道的事情。

我建议不要使用触发器来运行它。如果您有PL / SQL代码来更新价格,那么请包含代码以更新产品。也许更好的是,您可以将价格与产品取消关联,这样您根本不需要更新产品记录,只需根据需要查看产品的当前价格。

不要像这样在触发器处理中包含提交。如果用户事务未提交,那么您提交的更改将不再有效,但仍将保留,因此您可以使用回滚后不存在的价格更新产品。

请勿在代码中禁用/启用触发器。如果你必须这样做,那么你的设计是有缺陷的。

您正尝试在执行代码时使用全局变量。这也应该避免。