2016-06-17 7 views
0

人が注文し、各注文にアクションがあり、テーブルがcm_ord_order_actionというシステムを持っています。アクションが失敗することがあるので、失敗した注文アクションの情報を取得し、cm_ord_failed_orderというテーブルを作成するトリガーを作成する必要があります。トリガーと手続きによってテーブルが更新されない

トリガを以下に示します。

CREATE OR REPLACE TRIGGER CM.TRGID_CM_ORD_FAILED_ORDER 
AFTER UPDATE ON CM.CM_ORD_ORDER_ACTION 
FOR EACH ROW 
BEGIN 
    IF (:new.STATUS = 'FA') THEN 
     CM.CM_FAILED_ORDER_MLT(:new.order_unit_id, :new.order_id, :new.action_type); 
    END IF; 
END; 
/

このトリガがテーブルを更新するプロシージャにパラメータを渡します。

CREATE OR REPLACE PROCEDURE CM_FAILED_ORDER_MLT(
v_order_unit_id NUMBER, 
v_order_id in NUMBER, 
v_action_type in VARCHAR) 

AS 
v_lob varchar(100); 
v_step varchar(100); 
v_error varchar(200); 

BEGIN 

SELECT 
    ITEM.LOB_NAME, ST.STEP_NAME, ASS.STEP_ERROR 
    INTO v_lob, v_step, v_error   
FROM 
    CM.CM_ORD_ORDER_ACTION OA 
    INNER JOIN CM.CM_ORD_ASSIGNMENTS ASS 
     ON OA.ORDER_UNIT_ID = ASS.ORDER_ACTION_ID 
    INNER JOIN CM.CM_ORD_PROCESS_STEP ST 
     ON ST.ORD_PROCESS_STEP_ID = ASS.STEP_ID 
    INNER JOIN CM.CM_ORD_AP_ITEM ITEM 
     ON ITEM.AP_SUBSCRIBER_ID = OA.AP_SUBSCRIBER_ID 
WHERE ASS.COMPLETION_STATUS = 'FA' 
AND OA.ORDER_ID = v_order_id 
AND OA.ORDER_UNIT_ID = v_order_unit_id 
GROUP BY OA.ORDER_UNIT_ID, ITEM.LOB_NAME, ST.STEP_NAME, ASS.STEP_ERROR; 

INSERT INTO CM_ORD_FAILED_ORDER (ORDER_ID, FAILED_DATE, ORDER_ACTION_ID, ACTION_TYPE, LOB, STEP, ERROR) 
    VALUES (v_order_id, sysdate, v_order_unit_id, v_action_type, v_lob, v_step, v_error); 

END CM_FAILED_ORDER_MLT; 
/

間違って何かがここにおそらくありますので: A - にもかかわらずトリガはcm_ord_order_actionの更新後のものです。トリガが有効な場合、ステータスは更新されませんが、トリガを無効にすると状態が更新されます。

B - cm_ord_failed_orderテーブルに情報が入力されていません。

ありがとうございます。

+0

なぜ更新前に使用しないのですか? – kevinsky

+1

更新はどのように実行されますか?プロシージャは例外をスローしていますか(データが見つかりません?)、トリガーが通過しますが、更新を実行しているものが何かをしゃべって/無視していますか?何が起こるかを確認するために手動でアップデートをやってみましたか、デバッグしましたか? –

+1

私の推測では、あなたのトリガーはエラーを投げます。私の推測では、それは突然のテーブルエラーです。それはあなたが実際に見ているものですか?これらのエラーを飲み込んでいるコードがありますか?プロシージャから 'CM_ORD_ORDER_ACTION'への参照を削除したいと思うでしょう - あなたはトリガから必要なテーブルからすべての値を渡す必要があります。 –

答えて

1

:NEW疑似コードで更新されている行の詳細があり、再度照会する必要がないトリガーで挿入を直接実行することで、スクリプトが何らかの理由で無視または破棄するという変更テーブルのエラーを回避できます。ローカル変数を使用せずにinsert...selectを実行することもできます。

私は、これは大まかな翻訳であると思う:

CREATE OR REPLACE TRIGGER CM.TRGID_CM_ORD_FAILED_ORDER 
AFTER UPDATE ON CM.CM_ORD_ORDER_ACTION 
FOR EACH ROW 
WHEN (new.STATUS = 'FA') 
BEGIN 

    INSERT INTO CM_ORD_FAILED_ORDER (ORDER_ID, FAILED_DATE, ORDER_ACTION_ID, ACTION_TYPE, 
    LOB, STEP, ERROR) 
    SELECT 
    DISTINCT :new.ORDER_ID, sysdate, :new.Order_Unit_Id, :new.Action_Type, 
     ITEM.LOB_NAME, ST.STEP_NAME, ASS.STEP_ERROR 
    FROM 
    CM.CM_ORD_ASSIGNMENTS ASS 
    INNER JOIN CM.CM_ORD_PROCESS_STEP ST 
     ON ST.ORD_PROCESS_STEP_ID = ASS.STEP_ID 
    CROSS JOIN CM.CM_ORD_AP_ITEM ITEM 
    WHERE ASS.ORDER_ACTION_ID = :new.ORDER_UNIT_ID 
    AND ASS.COMPLETION_STATUS = :new.STATUS 
    AND ITEM.AP_SUBSCRIBER_ID = :new.AP_SUBSCRIBER_ID; 

END CM_FAILED_ORDER_MLT; 
/

DISTINCT(代わりに、グループ化の)とCROSS JOINは、あなたがあなたの元のクエリでは、それかもしれない、あなたのテーブル構造とデータなしで結合条件が欠落している示唆そうではありません。

別の方法としては、プロシージャで挿入を続けるが、それはあなたが既に合格していない変更表から必要なカラムだけのようですから、別の引数として:new AP_SUBSCRIBER_ID`を渡すことができます。

あなたのトリガーは、AFTER UPDATEではなく、BEFORE UPDATEでもかまいません。

+1

私は、cm_ord_ap_itemがそのクエリの他のテーブルのいずれにも結合されていなかったため、最初にOP内に 'cm.cm_ord_order_action'テーブルが含まれていたのは当然です。しかし、その猫を肌にさらす方法は複数あります! * {;-) – Boneist

0

同様@JustinCaveは、あなたがテーブルerror変異していることは明らかである、言った:我々は行レベル・トリガーコード内からの問合せに トリガテーブルを参照しようとすると、テーブルの例外を変異さ

が発生し

CM_ORD_ORDER_ACTIONのトリガでは、同じテーブルから選択しています。 CM_ORD_ORDER_ACTIONを参照せずに手順でクエリをやり直してください。

1

参加クロスの必要性を回避するアレックスのソリューションは、に手順を変更するだろうに代わる:

create or replace procedure cm_failed_order_mlt (v_order_unit_id number, 
               v_order_id in number, 
               v_action_type in varchar, 
               v_ap_subscriber_id in cm.cm_ord_order_action.ap_subscriber_id%type) 

as 
    v_lob varchar(100); 
    v_step varchar(100); 
    v_error varchar(200); 
begin 
    select distinct lob_name 
    into v_lob 
    from cm.cm_ord_ap_item 
    where ap_subscriber_id = v_ap_subscriber_id; 

    select distinct st.step_name, ass.step_error 
    into v_step, v_error   
    from cm.cm_ord_assignments ass 
     inner join cm.cm_ord_process_step st on st.ord_process_step_id = ass.step_id 
    where ass.completion_status = 'FA' 
    and ass.order_action_id = v_order_id 
    and oa.order_unit_id = v_order_unit_id; 

    insert into cm_ord_failed_order (order_id, failed_date, order_action_id, action_type, lob, step, error) 
    values (v_order_id, sysdate, v_order_unit_id, v_action_type, v_lob, v_step, v_error); 

end cm_failed_order_mlt; 
/

それとも、単にスカラー副問合せと交換し、アレックスのソリューションに参加クロスを削除します例:

select (select distinct lob_name from cm.cm_ord_ap_item where ap_subscriber_id = v_ap_subscriber_id), ... 
+1

*疑問*最初のクエリは複数の行を取得するため、元のクエリにgroup-by句を指定する必要があります。そのため、代わりに 'distinct'を残しました。しかし、テーブル/データがなければ、私は激しく推測しています。グループ化は重複しているかもしれないし、重複が他の場所から来ているかもしれない... –

+0

ああ、良い点。私はそのクエリにも別名を追加します - 私はメインクエリから、最大で1行が返されると仮定しています。そして今、あなたはそれに言及します、私は2番目のクエリでグループを別のものにも切り替えます。 – Boneist

関連する問題