我需要一些帮助,因为我不知道这段代码的问题在哪里。
我有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;
答案 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代码来更新价格,那么请包含代码以更新产品。也许更好的是,您可以将价格与产品取消关联,这样您根本不需要更新产品记录,只需根据需要查看产品的当前价格。
不要像这样在触发器处理中包含提交。如果用户事务未提交,那么您提交的更改将不再有效,但仍将保留,因此您可以使用回滚后不存在的价格更新产品。
请勿在代码中禁用/启用触发器。如果你必须这样做,那么你的设计是有缺陷的。
您正尝试在执行代码时使用全局变量。这也应该避免。