2017-03-14 7 views
0

このコードのどこに問題があるかわからないので、助けが必要です。パッケージ、トリガー、およびプロシージャは正常に動作しません

私は2つのテーブルを持っています。商品(id、..、currentPrice)と価格(id、product_id、日付、価格)。 Prices.priceの値が挿入、更新、または削除されたときにProducts.currentPriceの値を自動的に更新するトリガーとプロシージャを作成する必要があります。 私はパッケージ、2つのトリガとプロシージャを作成し、それらはすべてコンパイルOKですが、挿入、更新、または値を削除すると何も起こりません。 しかし、手作業を呼び出して、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

は、ここに私のコードです。まず、2つのトリガーを使用して一連の作業を実行しようとしています。トリガー発射の順序は保証されません。 1つのトリガーで以下を考慮してください。

第2に、procでは自律型トランザクションを指定しますが、コミットしません。

これらはコードを助けますが、知っておくべきことがいくつかあります。

トリガーでこれを実行しないことをおすすめします。価格を更新するPL/SQLコードがある場合は、コードを組み込んで製品を更新してください。おそらくまだ良いことですが、製品の価格を製品から切り離して、製品の記録をまったく更新する必要がなく、必要に応じてオンデマンドで製品の現在の価格を調べることができます。

このようなトリガー処理では、コミットを含めないでください。ユーザー・トランザクションがコミットしない場合、その中で変更をコミットしても有効でなくなりますが、ロールバック後に存在しない価格で製品を更新する可能性があります。

コード内でトリガーを無効/有効にしないでください。これを行う必要がある場合は、デザインに欠陥があります。

コードの実行中にグローバル変数を使用しようとしています。これも避けるべきです。

+0

私はPL/SQLの初心者です。このコードは、学習目的で行うより大きな割り当ての小さな部分の1つです。私はトリガーと手順を使用する必要があります。私はあなたが私に言ったことを読んだが、私はOracle PL/SQLの「ノブ」なので、うまくいきませんでした。もし私があなたの言葉を正しく得たら、私はCOMMITを加えるべきです。 ... – MaliVragolan

+0

実際には、PRAGMA AUTONOMOUS TRANSACTIONをそのprocから削除し、他の外部procsまたはproc呼び出しのいずれかでトランザクションを通常のトランザクションとしてコミットする必要があります。 – unleashed

+0

しかし、PRAGMAを削除すると、その値を変更することを禁じている強制トリガがあるので、ProductsのcurrentPriceフィールドを更新できません。この手続きを呼び出すAFTERトリガーの中でPRAGMAを動かすことができます。しかし、私が悲しいように、自分の作品上の手順がパッケージと2トリガーとの組み合わせではないと私は解決策を見ることができます。 – MaliVragolan

関連する問題