0

テーブルストックのトリガーを作成しました

テーブルのスキーマは次のとおりです。

create table stock(item_code varchar2(2) primary key, p_qty number(2),s_qty number(2));

トリガーは次のとおりです。

CREATE OR REPLACE TRIGGER TR_STOCK BEFORE UPDATE OF S_QTY ON STOCK FOR EACH ROW
DECLARE
    V_P STOCK.P_QTY%TYPE;
    V_S STOCK.S_QTY%TYPE;
    V_I VARCHAR2(2);
BEGIN
    V_S:=:NEW.S_QTY;
    V_I:=:NEW.ITEM_CODE;
    SELECT P_QTY INTO V_P FROM STOCK WHERE ITEM_CODE=V_I;
    IF V_S>V_P THEN
        RAISE_APPLICATION_ERROR(-20400,'SOLD QTY CANNOT EXCEED PURCHASED QTY...');
    END IF;
END;
/

これで、更新クエリを実行するたびに、テーブルが変化していると表示され、次のエラーのフラグが立てられます。

update stock set s_qty=2 where item_code='i4'
       *
ERROR at line 1:
ORA-04091: table HR.STOCK is mutating, trigger/function may not see it
ORA-06512: at "HR.TR_STOCK", line 8
ORA-04088: error during execution of trigger 'HR.TR_STOCK'

この特定の問題について何か助けはありますか?

4

2 に答える 2

2

STOCKテーブルをクエリする必要はありません。:NEW.P_QTY:NEW.S_QTYフィールドを直接比較するだけです

CREATE OR REPLACE TRIGGER TR_STOCK BEFORE UPDATE OF S_QTY ON STOCK FOR EACH ROW
DECLARE
BEGIN
    IF :new.s_qty > :new.p_qty THEN
        RAISE_APPLICATION_ERROR(-20400,'SOLD QTY CANNOT EXCEED PURCHASED QTY...');
    END IF;
END;
/
于 2012-06-25T15:47:50.173 に答える
2

データベース制約を使用してこのロジックを実装することを検討する必要があります。その場合、トリガーはまったく必要ありません。

ALTER TABLE hr.stock 
ADD CONSTRAINT stock_ck1
CHECK (
  s_qty <= p_qty
)

トリガーには、制約と比較して多くの欠点があります。

  • トリガーは既存のデータ行を考慮しません。必要に応じて、制約でこれを行うことができます。
  • トリガーは、行ごとFOR EACH ROWにSQLエンジンとPL/SQLエンジンの間でコンテキストを切り替える必要があるため、 orステートメントの実行のオーバーヘッドが増加します。これは、行数が増えるにつれて加算されます。INSERTUPDATE
  • Oracle は、SQL ステートメントを最適化するときに制約を使用できます (制約にWHERE違反する句はCHECK、行を検査する必要なしに行を返さないことを知っています)。

トリガーを使用してエラー メッセージを表示している場合は、セーフガードとして制約を付けて、これをアプリケーション ロジックに移動することを検討する必要があります。

于 2012-06-27T23:16:04.583 に答える