0

トリガーの問題は何ですか? オラクルにヒキガエルを使用しています
このSQLヒキガエルを実行した後、このメッセージが表示され、それ以上は表示されません!:

Warning: compiled but with compilation errors

そしてトリガーが効かない

私のトリガーはここにあります:

CREATE OR REPLACE TRIGGER trg_delete_mmtp_user_feature
   BEFORE DELETE
   ON mmtp_user
   FOR EACH ROW
BEGIN
-- for these cases delete not allowed
   IF ((SELECT COUNT (*)
          FROM payment p INNER JOIN mmtp_user mt
               ON mt.customer_id = p.requester_id
         WHERE p.rp_reason_id = 20 AND mt.mmtp_user_id = :OLD.mmtp_user_id) >
                                                                             0
      )
   THEN
      raise_application_error
             (-20654,
              'Query has attempted to delete MMTP_USER with existing payment'
             );

   ELSE                            --befor deleting features should be deleted
      DELETE FROM mmtp_user_feature
            WHERE mmtp_user_id = :OLD.mmtp_user_id;
   END IF;
END;
/

削除すると、次のメッセージが表示されます。

ORA-04098: trigger 'DEVX2.TRG_DELETE_MMTP_USER_FEATURE' is invalid and failed re-validation
4

2 に答える 2

5

コンパイルエラーが発生する理由は、IF 句で SELECT ステートメントを使用できないためです。したがって、次のように分割する必要があります。

....
DECLARE
    n pls_integer;
BEGIN
    SELECT COUNT (*)
    into n
    FROM payment p INNER JOIN mmtp_user mt
               ON mt.customer_id = p.requester_id
    WHERE p.rp_reason_id = 20 AND mt.mmtp_user_id = :OLD.mmtp_user_id
-- for these cases delete not allowed
   IF n > 0
   THEN
....

Florin が指摘するように、ランタイム変更テーブル エラーが発生することがわかります。トリガーを所有するテーブルにアクセスするトリガーにクエリを配置すると、Oracle はこのエラーをスローします。これは、テーブルが不安定な状態にあり、クエリの結果が予測できないために発生します。

ミューティング テーブル エラーはほとんどの場合、不適切なデータ モデルの指標であり、その原因は不十分な正規化です。つまり、それらを修正するには、ビジネス ルールの知識が必要です。この場合、明らかな解決策は次のようになります。

SELECT COUNT (*)
into n
FROM payment p 
WHERE p.requester_id = :OLD.customer_id
AND p.rp_reason_id = 20 

user_idこれは、 と の間に1 対 1 の関係がある場合に機能しcustomer_idます。そのような関係がない場合は、ビジネス ルールに関する知識を使用して解決策を見つけなければなりません。

ちなみに、COUNT(*) を使用して存在をテストすることは、スケーリングするソリューションではありません。お支払い回数の多いお客様はお時間がかかります。少なくとも1 つのそのようなレコードを持っていることだけが必要な場合、これは多くの無駄な労力です。クエリに追加and rownum = 1すると、不要な作業が減ります。

于 2013-02-05T07:22:58.857 に答える
2

問題は

   SELECT COUNT (*)
              FROM payment p INNER JOIN mmtp_user mt
                   ON mt.customer_id = p.requester_id
             WHERE p.rp_reason_id = 20 AND mt.mmtp_user_id = :OLD.mmtp_user_id

更新/削除されているテーブルを読んでいるので、テーブルの変更エラーが発生します。

たぶん、それを確認するだけなら

SELECT COUNT (*)
          FROM payment p 
          WHERE :OLD:customer_id = p.requester_id
            and p.rp_reason_id = 20  

はゼロより大きいですが、十分ですか?

于 2013-02-05T07:06:27.653 に答える