1

以下のような要件があります。

table1
------------------------
A    B     C    D   E    
------------------------
1    2     *    P    Q
1    2     A    Q    P
1    3     B    W    U
-----------------------

A B Cprimary keyオンですtable1

table2
------------------------
A    B     C    
------------------------
1    2     1   
1    2     2   
1    2     A    
------------------------

列は、テーブル 1A B Cの列のテーブル 2 の複合外部キーとして実装する必要がありますA B C。唯一の例外は、C親テーブル (テーブル 1) の列が、提供された子テーブル(テーブル 2)* に任意の値を表示でき 、両方で同じである場合です。テーブル。column Ccolumn Acolumn B

トリガーが最小限の実装を探しています。現在、この奇妙な要件のため、外部キーを作成できません。

別のアプローチを提案して、私の一日を作ってください:)

4

2 に答える 2

2

これはモデルの問題だと思います。どちらのテーブルも 2 つの異なるタイプのものを表しているように見えるため、通常の FK 制約は機能しません。

両方のテーブルを 2 つに分割する必要があると思います。

table1_noC
------------------------
A    B     D   E    
------------------------
1    2     P    Q

table2_noC (with a FK to table1_noC)
------------------------
A    B     C    
------------------------
1    2     1   
1    2     2   
------------------------

table1_C
------------------------
A    B     C    D   E    
------------------------
1    2     A    Q    P
1    3     B    W    U
-----------------------

table2_C (with a FK to table1_C)
------------------------
A    B     C    
------------------------
1    2     A    
------------------------

その後、 +を組み合わせたビューとtable1_noC+table1_Cを組み合わせた別のビューを使用して、元のデザインを再作成できます。必要に応じて、"代わりに" トリガーをビューに追加して、ビューの DML を基になるテーブルの必要な DML に変換することもできます。table2_noCtable2_C

于 2012-08-28T08:23:57.553 に答える
2

この問題は、新しい構造を必要とせずに対処できます。子テーブル (table2) に new_column (NEW_C) を導入し、「列 C」の代わりにこの列を外部キー制約で使用するだけです。手順は次のとおりです。

1>alter table2 add (new_c varchar2(1));

2> update table2 set new_c= c;

colum C3> FKの代わりに新しく導入された列 NEW_C を使用する

alter table table2
  add constraint
  fk_ref_table1 FOREIGN KEY (A,B,**NEW_C**)    
  references table1 (A,B,C);

4>子テーブルに単純な挿入/更新トリガーを作成して、新しい列を維持しますNEW_C

CREATE OR REPLACE maintain_new_c
 BEFORE
  INSERT OR UPDATE
  ON TABLE2 REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW
DECLARE
v_count pls_integer;
BEGIN
 SELECT COUNT(1) 
   INTO v_count
   FROM table1 t1    
  WHERE t1.c='*'
    AND t1.a= :NEW.a 
    AND t1.b= :NEW.b;

  IF v_count=0 THEN
    new_c := :NEW.c ;
  ELSE
    new_c := '*';
  END IF;

EXCEPTION
   WHEN OTHERS THEN
   RAISE_APPLICATION_ERROR..........
END;

別の方法は、子テーブルに新しい仮想列 (Oracle 11g) を導入することです。決定論的な pl/sql 関数を使用してこの仮想列を導出し、仮想列を使用して外部キー制約を作成します。

ただし、毎回仮想列を派生させてチェックする必要があるため、親テーブルの更新/削除操作が影響を受けるため、トリガーベースのアプローチを好みます。

于 2012-08-29T04:08:18.857 に答える