2011-12-06 9 views
2

この混乱しやすい質問、壁面、ひどいトリガーについては、事前にお詫びします。私は小売店の小規模なデータベースを設計しており、店内で注文を受け取り、オンサイトの倉庫/在庫室から製品を配送します。オラクル製品からの在庫数量を削除し、オーダーラインに追加する

今度は、注文エンティティはorder_lineエンティティと1対多の関係にあり、商品との関係が多岐にわたります(在庫自体に保存されます)。 order_lineエンティティはリンクエンティティであり、多対多の関係を解決するので、それはすべて良いことです。明確にするために、それは製品ごとに1つの注文ラインです。

私がしたいのは、order_line(数量属性を持つ)が作成されたときに、適切な商品に十分な在庫があることを最初に確認するようにしたい場合です(数量が3の場合、在庫は少なくとも3でなければなりません)それ以外の場合は、エラーをスローする必要があります。

成功した場合は、それに応じて数量と在庫属性を更新したいと思います。 order_lineに小計の値を追加することもできます(私はこれをまだ試していません)。次にorderエンティティの合計値を計算するために使用できます。

だから私はこれとかなり混乱しているので、私は少しガイダンスを探しています。

CREATE OR REPLACE TRIGGER check_order_line 
BEFORE INSERT OR UPDATE ON order_line 

for each row 
BEGIN 
select order_line.quantity, products.stock from order_lines right join products on  order_line.product_no=products.product_no; 
if(order_line.quantity>products.stock) then 
RAISE_APPLICATION_ERROR(-20103, 'Insufficient Stock'); 
ELSE 
products.stock := products.stock - quantity; 
dbms_output.put('Successful'); 
END IF; 
END; 
. 
run 

エラー私は取得しています:私が試した何

2/1  PL/SQL: SQL Statement ignored 
2/49  PL/SQL: ORA-00942: table or view does not exist 
3/1  PL/SQL: Statement ignored 
3/15  PLS-00357: Table,View Or Sequence reference 'ORDER_LINE.QUANTITY' 
    not allowed in this context 

  • 私は最初の2つのエラーについてはよく分かりません。問題のテーブルは となっていますが、明らかにorder_lineと呼ばれています。
  • また、最後のエラーを解決するためにproducts.stockとorder_line 数量の変数を宣言しようとしました。これはIIRCをコンパイルしますが、 は実際にはテーブルを更新していないと思われます。
  • 私は他のアクションについてあまり心配していません、私はおそらく、 テーブルのステートメントを更新する必要がありますが、今のところ私はちょうど トリガー条件を取得することに焦点を当てています。
  • いずれかが右の の方向を指すことができ、何か面白いエラーを指摘したら、私はそれを感謝します。

    ありがとうございます。このトリガーの怪物で目を傷つけることをお詫びします。

+0

を提案CHECK制約を必要とする理由です最後に 'run'コマンドいることは何ですか?どのツールでCREATE TRIGGERを実行していますか? –

答えて

3

値を強制するためにproducts.stockに制約を置く> -1です:

ALTER TABLE products add CONSTRAINT has_stock CHECK (stock >-1); 

その後、単一のトランザクションとしてupdateinsertを行います。

在庫が不足しているとトランザクションが失敗し、トリガーに関連する問題は発生しません。

例えば(あなたが値を保持する変数v_product_costを宣言する必要があります)あなたがあなたのupdateRETURNING句を使用して、それを得ることができ、この時点で株価を持っていないと仮定:

UPDATE product SET products.stock = products.stock - quantity_required 
WHERE product_id=id_of_product 
RETURNING products.value INTO v_product_cost 

その後、この値を挿入に使用することができます。

+0

こんにちはKevin、私は制約を追加します、ありがとう。これは完全に機能する単純なベースレベルのソリューションのようです。私は明日更新を試してみましょう。応答してくれてありがとう、本当にあなたの助けに感謝します。 –

1
  1. 最後のrunコマンドは意味がありません。これはSQL Serverの構文です。
  2. クエリでは、テーブルORDER_LINES(複数)を参照しています。しかし、トリガーはテーブルORDER_LINE(単数)で定義されています。私はORDER_LINEORDER_LINESの両方のテーブルを持っていないと仮定しますので、あなたのクエリがORDER_LINEテーブルを参照することを意図していました。
  3. 表Aに定義された行レベルのトリガーは、一般に表Aを照会することはできません。したがって、トリガーがORDER_LINEに定義されているため、ORDER_LINEを照会することはできません。実際には、トリガーを発生させた行に関する情報がほしいと思うので、実際にORDER_LINEテーブルに参加する必要はありません。 :NEWレコードの属性を参照するだけで済みます。
  4. SELECT PL/SQLの文は、結果を使用して何か処理を行う必要があります。おそらく、あなたの意図はSELECT ... INTOローカル変数を行うことです。
  5. PRODUCTSテーブルを更新する場合は、実際にUPDATEを実行する必要があります。一緒にすべてのことを置く

、私の推測では、あなたが

CREATE OR REPLACE TRIGGER check_order_line 
    BEFORE INSERT OR UPDATE ON order_line 
    for each row 
DECLARE 
    l_current_stock products.stock%type; 
BEGIN 
    select products.stock 
    into l_current_stock 
    from products 
    where product_no = :new.product_no; 
    if(:new.quantity > l_current_stock) then 
    RAISE_APPLICATION_ERROR(-20103, 'Insufficient Stock'); 
    else 
    update products 
     set stock := stock - :new.quantity 
    where product_no := :new.product_no; 
    end if; 
END; 

のようなものがあるすべてのことが言われている、しかし、トリガは、一般的に正しい方法ではないでしょうに見えるトリガーを作成しようとしているということですこの種の問題を解決する。メンテナンスの観点からは、ストアドプロシージャPROCESS_ORDERをすべてのORDER_LINE行に挿入し、すべてのPRODUCTS行を更新すると、追跡とデバッグがはるかに簡単になります。トリガに埋め込まれるビジネスロジックが増えるほど、アプリケーションの流れに追随することが困難になり、巻き返すことがほとんど不可能な意図しない更新のネストが簡単に終わることになります。

また、マルチユーザーシステムでは何が起こるかに注意してください。セッションAはPRODUCTSテーブルを照会し、STOCKが5であることを確認し、その製品の4ユニットの注文を受け入れることができます。しかし、セッションAがコミットを発行する前に、セッションBはPRODUCTSテーブルの同じ行を照会し、同じSTOCKを5と見て、3単位の注文を受け入れます。セッションBのUPDATEステートメントは、セッションAがコミットするまでブロックされます。しかし、Aがコミットし、Bがコミットすると、両方の注文が入力され、PRODUCTSテーブルはSTOCKの-2を表示します。あなたはケビンが

ALTER TABLE products 
    ADD CONSTRAINT chk_positive_stock CHECK(stock >= 0); 
+0

こんにちはJustin、Order_linesの誤植を見つけてくれてありがとう - あなたが正しいです、私はこのシステムではorder_lineしか使っていません。ポイント3に関して、私はあなたが何を意味しているかを見ます。私はテーブルミューテーションエラーを起こすと思いますので、私はあなたの提案を見ていきます。ポイント4:それは理にかなっています。 悲しいことに、授業仕様には3つのトリガーが必要です。手順には授与されません(私にとっては馬鹿だと思われます)。これが第3のトリガーです。それがあなただったら、この機能のためのトリガをしてもらえませんか?あなたが与えた理由は、別のアイデアを見なければならないと思っているからです。 –

関連する問題