0

新しい請求書の行を追加するときに、製品の手持ち数量を更新する単純なトリガーに取り組んでいます。私はそれがうまくいきました。しかし、実際のアプリケーションでは、更新を許可する前に QOH が十分であることを確認することが賢明であると考え始めました。そのための別のトリガーを作成できると確信していますが、トリガー内の条件ステートメントで 2 つのテーブルを結合できるかどうかを確認したいと思います。

これは私が得た限りです。そこに SELECT ステートメントを追加すると、すべての地獄が解き放たれるため、条件を呼び出す前に PRODUCT.P_QOH を宣言する方法に少し困惑しています。

CREATE OR REPLACE TRIGGER trg_prod_QOH_on_line_add
    BEFORE INSERT ON LINE
    FOR EACH ROW
    BEGIN
        IF :NEW.LINE_UNITS > PRODUCT.P_QOH THEN
            RAISE_APPLICATION_ERROR(-20202, 'Insufficient quantity on hand');
        ELSE
            UPDATE PRODUCT
                SET P_QOH = P+QOH - :NEW.LINE_UNITS;
                WHERE PRODUC.P_CODE = :NEW.P_CODE;
        END IF;
    END;
/

おそらく別の方法があると言ったので、これは私にとって大きな問題ではありません。私はこのことを学び始めたばかりで、何が可能かを見たいと思っています。ご協力いただきありがとうございます。

4

1 に答える 1

3

トリガーを介してこのようなルールを適用しようとすると、危険な領域に入ります。あなたが求めている解決策は次のとおりです。

create or replace trigger trg_prod_qoh_on_line_add
    before insert on line
    for each row
    declare
        v_qoh product.p_qoh%type;
    begin
        select p_qoh
        into   v_qoh
        from   product
        where  product.p_code = :new.p_code;

        if :new.line_units > v_qoh then
            raise_application_error(-20202, 'Insufficient quantity on hand');
        else
            update product
                set p_qoh = p_qoh - :new.line_units
                where product.p_code = :new.p_code;
        end if;
    end;

ただし、これは複数の同時ユーザーがいるシステムでは安全なソリューションではありません。製品「X」に p_qoh=10 があり、2 人のユーザーがこれを行うとします。

user1> insert into line (p_code, line_units) values ('X', 7);

user2> insert into line (p_code, line_units) values ('X', 8);

user1> commit;

user2> commit;

両方のセッションで、'X' が p_qoh = 10 であることがわかるため、両方が成功し、product.p_qoh は -5 になります。すべてが腐敗しています!

安全な解決策は、製品にチェック制約を作成することです。

alter table product add constraint prod_qoh_chk check (p_qoh >= 0);

これで、トリガーは次のようになります。

create or replace trigger trg_prod_qoh_on_line_add
    before insert on line
    for each row
    begin
        update product
        set p_qoh = p+qoh - :new.line_units;
        where produc.p_code = :new.p_code;
    end;

これにより、次のような分かりにくいエラー メッセージが表示されます。

ORA-02290: check constraint (MYSCHEMA.PROD_QOH_CHECK) violated

これをトリガーにトラップして、必要なメッセージを与えることができます。

create or replace trigger trg_prod_qoh_on_line_add
    before insert on line
    for each row
    begin
        update product
        set p_qoh = p+qoh - :new.line_units;
        where produc.p_code = :new.p_code;
    exception
        when others then
            if sqlerrm like 'ORA-02291:%(MYSCHEMA.PROD_QOH_CHECK)%' then
                raise_application_error(-20202,'Insufficient quantity on hand');
            else
                raise;
            end if;
    end;

上記の 2 ユーザーのシナリオを再実行すると、次のようになります。

user1> insert into line (p_code, line_units) values ('X', 7);

user2> insert into line (p_code, line_units) values ('X', 8);

user1> commit;

この時点で、user2 の挿入は次のエラー メッセージで失敗します。

ORA-20202: Insufficient quantity on hand
于 2012-06-18T10:04:25.833 に答える