2017-12-21 14 views
2

In DB2, nehme ich habe 3 Tabellen: T1, T2, T3: DB2: Fremdschlüssel-Constraints zwischen mehreren Tabellen

CREATE TABLE T1 (
    T1_ID INTEGER NOT NULL, 
    PRIMARY KEY (ID) 
); 

CREATE TABLE T2 (
    T2_T1 INTEGER NOT NULL, -- parent entity ID from T1 
    T2_ID INTEGER NOT NULL, 
    PRIMARY KEY (T2_T1, T2_ID), 
); 

CREATE TABLE T3 (
    T3_T1 INTEGER NOT NULL, -- parent entity ID from T1 
    T3_T2 INTEGER NOT NULL, -- parent entity ID from T2 
    T3_ID INTEGER NOT NULL, 
    PRIMARY KEY (T3_T1, T3_T2, T3_ID) 
); 

Ich möchte FK Beziehungen in einer Art und Weise definieren, es Löschung der Aufzeichnung verbieten würde in T2, wenn ein verbundener Datensatz in T3 vorhanden ist, aber gleichzeitig, wenn ich einen Datensatz aus T1 lösche, sollten Datensätze in T2 und T3 automatisch gelöscht werden.

Ist es möglich, nur FK-Bedingungen zu definieren, um diese Anforderungen zu erfüllen? Oder es kann nicht erreicht werden, ohne einen Code zu schreiben, der zuerst entsprechende Datensätze aus T3, dann aus T2 und erst dann aus T1 löscht?

aktualisieren: ein tatsächlicher DB2 10.5 Code, den ich zu laufen bin versucht:

CREATE TABLE t1 (
    t1_id INTEGER NOT NULL, 
    PRIMARY KEY(t1_id) 
) 

CREATE TABLE t2 (
    t2_t1 INTEGER NOT NULL, 
    t2_id INTEGER NOT NULL, 
    PRIMARY KEY (t2_t1, t2_id), 
    CONSTRAINT t2_fk_t1 
    FOREIGN KEY (t2_t1) 
    REFERENCES t1 (t1_id) 
    ON DELETE CASCADE 
) 

CREATE TABLE t3 (
    t3_t1 INTEGER NOT NULL, 
    t3_t2 INTEGER NOT NULL, 
    t3_id INTEGER NOT NULL, 
    PRIMARY KEY (t3_t1, t3_t2, t3_id), 
    CONSTRAINT t3_fk_t1 
    FOREIGN KEY (t3_t1) 
    REFERENCES t1 (t1_id) 
    ON DELETE CASCADE, 
    CONSTRAINT t3_fk_t2 
    FOREIGN KEY (t3_t1, t3_t2) 
    REFERENCES t2 (t2_t1, t2_id) 
    ON DELETE RESTRICT 
) 

Die letzte CREATE Anweisung schlägt mit dem folgenden Fehler:

SQL20255N FOREIGN KEY "T3_FK_T2" is not valid because it would cause a descendent table "S.T3" to be delete-connected to its ancestor table "S.T1" through multiple relationships with conflicting delete rules. The conflict is between the delete rules of constraints "S.T3.T3_FK_T1" and "S.T3.T3_FK_T2" on the descendent table. Reason code = "3". SQLSTATE=42915

+0

Ja, es kann möglich sein ***** ACHTUNG ***** Wenn Sie eine FK-Kaskade falsch bekommen, wird es katastrophale Kaskadenfehler in Ihrem DB und Zeilen werden sowohl in Eltern-und Kind-Tabellen gelöscht werden .. Der sichere Weg, dies zu tun, ist, indem Sie restricten angeben. Mit einem Fremdschlüssel einschränken müssen Sie Datensätze in jeder Tabelle manuell sicherer löschen. ***** Beginnen Sie mit dem Zeichnen eines Bildes ****** – danny117

Antwort

0

Das sollte funktionieren. Auch wenn es ein wenig scheint seltsam, ist es nicht verboten, überlappende Einschränkungen zu haben.


CREATE TABLE t1 (
    t1_id INTEGER NOT NULL PRIMARY KEY 
); 

CREATE TABLE t2 (
    t2_t1 INTEGER NOT NULL REFERENCES t1(t1_id) ON DELETE CASCADE 
    , t2_id INTEGER NOT NULL 
    , PRIMARY KEY (t2_t1, t2_id) 
); 

CREATE TABLE t3 (
    t3_t1 INTEGER NOT NULL REFERENCES t1(t1_id) ON DELETE CASCADE 
    , t3_t2 INTEGER NOT NULL 
     , FOREIGN KEY (t3_t1,t3_t2) REFERENCES t2(t2_t1,t2_id) ON DELETE RESTRICT 
    , t3_id INTEGER NOT NULL 
     , PRIMARY KEY (t3_t1, t3_t2, t3_id) 
); 
INSERT INTO t1 (t1_id) VALUES (11), (12),(13), (14), (15); 
INSERT INTO t2 (t2_t1,t2_id) VALUES (11, 21), (12,22),(13,23), (14,24), (15,25); 
INSERT INTO t3 (t3_t1,t3_t2,t3_id) VALUES (11, 21,31), (12,22,32),(13,23,33), (14,24,34), (15,25,35); 


DELETE FROM t1 WHERE t1_id = 13; -- should succeed 
DELETE FROM t2 WHERE t2_id = 24; -- should fail 

SELECT * FROM t1; 
SELECT * FROM t2; 
SELECT * FROM t3; 
0

Ja, ist es möglich.

Erstellen Sie einfach einen Fremdschlüssel von T3 zu T2 und T1, T2 ist ein RESTRICT auf DELETE und T1 hat keine Aktion.

In T2, ein Fremdschlüssel zu T1 auch mit einer Kaskade löschen.

CREATE TABLE T1 (
    T1_ID INTEGER NOT NULL unique, 
    PRIMARY KEY (T1_ID) 
); 

CREATE TABLE T2 (
    T2_T1 INTEGER NOT NULL  constraint t2_t1_t1_id_fk 
      references t1 
       on delete cascade, -- parent entity ID from T1 
    T2_ID INTEGER NOT NULL unique, 
    PRIMARY KEY (T2_T1, T2_ID) 
); 

CREATE TABLE T3 (
    T3_T1 INTEGER NOT NULL constraint t3_t1_t1_id_fk 
     references t1 
      on delete cascade, -- parent entity ID from T1 
    T3_T2 INTEGER NOT NULL constraint t3_t2_t2_id_fk 
     references t2 (t2_id) on delete restrict, -- parent entity ID from T2 
    T3_ID INTEGER NOT NULL, 
    PRIMARY KEY (T3_T1, T3_T2, T3_ID) 
); 

Beachten Sie, können Sie auch einfach tun es aus der anderen Perspektive, falls Sie strenge Fremdschlüssel haben wollen. (Fremdschlüssel von den ID's zu den Referenzen!)

Im schlimmsten Fall gibt es immer Trigger, alles ist möglich. :)

+0

Ich versuche dies in DB2 10.5 und es würde nicht erlauben, T3 mit "widersprüchlichen Löschregeln" zu definieren ... – faraway

+0

Oh mein Gott. Habe DB2 leider nie benutzt, ich benutze Postgresql persönlich. Ich habe meine Antwort mit dem vollständigen Skript erstellt, nur für den Fall. –

+0

Entschuldigung, ich hätte es dem ursprünglichen Post geben sollen, wird jetzt aktualisiert. – faraway

Verwandte Themen