sql >> データベース >  >> RDS >> Oracle

ORA-04091:表[blah]が変化しています。トリガー/関数がそれを認識しない可能性があります

    トリガーが何をしようとしているのかについてのあなたの説明には同意できないと思います。このビジネスルールを適用することを意図しているように見えます。t1_appnt_eventの指定された値の場合、一度に1つの行のみがt1_prnt_t1_pkの非NULL値を持つことができます。 (2列目が同じ値であるかどうかは関係ありません。)

    興味深いことに、これはUPDATE OF t1_appnt_eventに対して定義されていますが、他の列に対しては定義されていないため、その列に別のトリガーがない限り、誰かが2番目の列を更新することでルールを破ることができると思います。

    このルールを適用する関数ベースのインデックスを作成して、トリガーを完全に取り除く方法があるかもしれません。私は1つの方法を思いついたが、それにはいくつかの仮定が必要である:

    • テーブルには数値の主​​キーがあります
    • 主キーとt1_prnt_t1_pkはどちらも常に正の数です

    これらの仮定が当てはまる場合は、次のような関数を作成できます。

    dev> create or replace function f( a number, b number ) return number deterministic as
      2  begin
      3    if a is null then return 0-b; else return a; end if;
      4  end;
    

    とこのようなインデックス:

    CREATE UNIQUE INDEX my_index ON my_table
      ( t1_appnt_event, f( t1_prnt_t1_pk, primary_key_column) );
    

    したがって、PMNT列がNULLである行は、主キーの逆数を2番目の値としてインデックスに表示されるため、互いに競合することはありません。 NULLでない行は、列の実際の(正の)値を使用します。制約違反を取得できる唯一の方法は、2つの行の両方の列に同じ非NULL値がある場合です。

    これはおそらく過度に「賢い」ですが、問題を回避するのに役立つ可能性があります。

    Paul Tomblinからの更新:igorがコメントに入れた元のアイデアへの更新を行いました:

     CREATE UNIQUE INDEX cappec_ccip_uniq_idx 
     ON tbl1 (t1_appnt_event, 
        CASE WHEN t1_prnt_t1_pk IS NOT NULL THEN 1 ELSE t1_pk END);
    


    1. mysqlselectqueryで2つの日付の間の日付のリストを取得する方法

    2. MySQLは、フィールド内の一部のテキストを検索して置換します

    3. SQLServerデータベースですべての外部キー制約を有効にするスクリプトを生成する方法-SQLServer/TSQLチュートリアルパート78

    4. 重複データの問題とその修正方法