Frage

Ich habe eine Tabelle (A), dessen Primärschlüssels ist entweder ein Fremdschlüssel der Tabelle (B) oder eine Tabelle (C).

create table A (
  akey number, 
  txt varchar2(10)
);

create table B (
  bkey number, 
  txt varchar2(10)
);

create table C (
  ckey number, 
  txt varchar2(10)
);

Was ich will, ist so etwas wie:

alter table A add constraint BorCkey foreign key (akey) references B(bkey)` or C(ckey);

Ist das möglich?

War es hilfreich?

Lösung

Nein, so etwas ist nicht möglich, in Oracle.

Ihre Optionen sind im Allgemeinen

  • Erstellen Sie zwei verschiedene Spalten (bkey und ckey) in A, wo bkey Referenzen B.bkey und ckey Referenzen C.ckey und erstellen eine Einschränkung, die sicherstellt, dass nur eine Nicht-NULL an jedem beliebigen Punkt in der Zeit.
  • Erstellen Sie eine Art von „kombinierten B & C“ entity, dass B & C haben Fremdschlüssel und die Fremdschlüssel in einer Referenz machen den Schlüssel dieser Kombination Einheit.

Wenn Sie eine Einschränkung, die sicherstellt, dass genau eine von zwei Spalten ist NULL und ist NOT NULL für jede Zeile

create table one_key( 
  col1 number, 
  col2 number, 
  check( nvl2(col1,1,0) + nvl2(col2,1,0) = 1 ) 
)

Andere Tipps

Ein Fremdschlüssel ist auf eine Fremd Tabelle .
Das bedeutet müssen Sie zwei ALTE TABLE-Anweisungen in dieser Situation Setup Fremdschlüssel verwenden, um die beiden Tabellen zu verweisen. Es gibt keine Möglichkeit, dort ein OR in der Beziehung angeben - der Wert in A.akey muß in beide B.bkey und C.ckey zur gleichen Zeit existieren würde . Zum Beispiel, wenn B.bkey einen Wert von NULL hat, aber C.ckey nicht - dann A.akey kann niemals einen Wert von NULL hat. Fremdschlüssel sind deferrable in Oracle, aber das Verhalten beschrieben ist, was Sie begegnen, wenn beide Fremdschlüssel gleichzeitig aktiviert sind - Sie werden nicht in der Lage sein, eine Einschränkung zu aktivieren, wenn alle die Werte nicht die Beziehung <. / p>

Sie müssen Ihre Bedürfnisse überprüfen, wie die Beziehung zu vereinfachen, so dass es nicht zwei Tabellen braucht sich um diese Arbeit zu machen.

Sounds wie Sie irgendeine Form von Subtyp / geordneter Typ Beziehung geht. Ein typisches Beispiel ist ‚Person‘, die entweder ein ‚Kunde‘ oder ein ‚Lieferant‘ sein können.

Sie haben könnten, in der Person Tabelle der eindeutige Schlüssel von PERSON_ID sowie ein Attribut PERSON_TYPE ( ‚CUST‘ oder 'SUPP). Wenn Sie den Primärschlüssel auf PERSON_ID erstellen, PERSON_TYPE Sie, dass in den Subtyp Tabellen (Lieferanten- / Kunden-) verweisen können.

Dann fügen Sie eine eindeutige Einschränkung auf der person_id, um sicherzustellen, dass jeder Wert von person_id entweder ein Kunde oder Lieferant sein muss, aber nicht beide, und Check-Einschränkungen auf den Subtyp Tabellen, so dass nur ein Typ in der Tabelle dargestellt ist.

create table person
  (person_id     number,
   person_type   varchar2(4),
   name          varchar2(10),
    constraint person_pk primary key (person_id, person_type),
    constraint person_id_uk unique (person_id));

create table supplier
  (supplier_id   number,
   supplier_type varchar2(4),
   blah          varchar2(10),
  constraint supplier_pk primary key (supplier_id, supplier_type),
  constraint supp_pers_fk foreign key  (supplier_id, supplier_type)
    REFERENCES person (person_id, person_type)
  )
/
alter table supplier add constraint supp_type_ck check (supplier_type = 'SUPP');

Es ist nicht schön, aber Typen / Subtypen sind mehr ein Objekt Konzept als ein relationaler ein.

Meine Lösung von Justin inspiriert:

CREATE OR REPLACE TRIGGER abc
  BEFORE INSERT OR UPDATE ON a
  FOR EACH ROW
  DECLARE
  v_testB NUMBER:= 0;
  v_testC NUMBER:= 0;
  BEGIN
    SELECT
      COUNT(bkey)
    INTO
      v_testB
    FROM
      b
    WHERE
      bkey = :new.aKey;
    SELECT
      COUNT(ckey)
    INTO
      v_testC
    FROM
      c
    WHERE
      ckey = :new.aKey;
    IF ((v_testB + v_testC) <> 1) THEN
      RAISE_APPLICATION_ERROR(-20002,'Foreign key to B or C missing.');
    END IF;
  END;
/
SHOW ERRORS TRIGGER abc

Erstellen Sie eine materialisierte Ansicht, dass die Gewerkschaften Tabellen B & C, und zeigen Sie Ihre FK Einschränkung der Ansicht

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top