0

指定された値に応じて、挿入/更新を実行しようとしているテーブルがあります。ただし、挿入はこの特定のテーブルでは機能しませんが、スクリプトが実行された以前のテーブルでは機能します。

この問題をテストするために、キーが存在するかどうかに応じて挿入または更新する oracle の sqldeveloper にいくつかの匿名ブロックを入れました。更新は正常に機能しているように見えますが、新しい行を挿入すると、何も挿入されません。

このテーブルがあった場合:

COFFEE_ID       TEA_ID        NAME      
    11             100        combo 1
    12             101        combo 2
    13             102        combo 3

これを行うと、何も挿入されず、代わりに次の無名ブロックに移動します。

   begin
      insert into COFFEE_TEA(COFFEE_ID, TEA_ID, NAME) values (14, 103, 'combo 4');
   exception when dup_val_on_index then 
      update ....
   end;

    ....

このテーブルのトリガーと関係があると思われます。これはBEFORE EACH ROWトリガー タイプであり、他のテーブルにデータを挿入します。トリガーには例外処理がないため、失敗する必要があると推測していますが、それを報告する必要はありません (スクリプトを実行しても sqldeveloper に表示されません)。

私の2つの質問は、

トリガーが実行されると、他のテーブルに挿入しようとしている ID が既に存在する場合はどうなりますか? 静かに失敗するように見えますか?

これをどのように修正するのが最善ですか?トリガーコード自体を変更できるかどうかはわかりませんが、匿名ブロック内でエラーをキャッチすることは可能でしょうか (実際に問題を引き起こしているのはトリガーであると仮定します)。もしそうなら、サイレントに失敗した場合にキャッチする例外をどのように知ることができますか?


sqldeveloper で例外を削除したところ、一意の制約に違反したことがわかりました。つまり、トリガーを介して他のテーブルにデータが挿入されていることが原因です。

4

2 に答える 2

3

あなたの追加情報は、あなたのトリガーがORA-00001、一意のキー違反を投げかけていることを示しています。これは、DUP_VAL_ON_INDEX 例外が処理するエラーです。したがって、 COFFEE_TEA のキー違反を処理するはずの例外ハンドラーも、トリガーからの例外を飲み込んでいるようです。混雑。

考えられる解決策は 2 つあります。1 つは、適切なエラー処理をトリガー コードに入れることです。もう 1 つは、データ読み込みルーチンに MERGE を使用することです。

アップサートを実行するためのメカニズムとして常に MERGE を好みます。これは、正当な期待状態を処理するために例外を使用するのが好きではないからです。 詳細をご覧ください

理想的には、両方を行う必要があります。トリガーは、自己完結型のコードであると想定されています。テーブルと対話するルーチンに未処理の例外を課すと、カプセル化が壊れます。

于 2012-10-03T14:46:53.877 に答える
0

トリガーは、テーブルのDMLプロセスを変更しません。COFFEE_TEA例外ブロックを削除します。がテーブルの場合、挿入は成功するか、エラーで失敗します。

つまり、がCOFFEE_TEAテーブルの場合、次のスクリプトは0を出力しません。

BEGIN
   INSERT INTO coffee_tea(COFFEE_ID, TEA_ID, NAME) values (14, 103, 'combo 4');
   dbms_output.put_line(sql%rowcount);
END;
于 2012-10-02T16:15:52.060 に答える