2016-03-25 9 views
0

Ich habe eine Tabelle, die von mehreren Tabellen referenziert wird (etwa 52) und außerdem haben einige der untergeordneten Tabellen mehrere Fremdschlüssel, die auch auf andere Tabellen verweisen.Wie Datensätze aus der übergeordneten Tabelle zu löschen, die von mehreren untergeordneten Tabellen referenziert wird?

Ich möchte einen Datensatz aus der übergeordneten Tabelle löschen, ich kann dies nicht tun, da ich Fehler erhalte "Die DELETE-Anweisung kollidierte mit der REFERENCE-Einschränkung" FK_xxx ". Der Konflikt trat in der Datenbank" MyDB "auf. dbo.A ", Spalte 'x'."

Ich möchte eine verallgemeinerte T-SQL-Lösung, die unabhängig von Tabellen und Anzahl der Referenzen ist.

+0

Bitte einige Codes anzeigen. Vielleicht kann ich Dir helfen. – Francisunoxx

Antwort

1

Sie müssen sich das Schlüsselwort "on delete" ansehen, das Teil der Fremdschlüssel-Einschränkungsdefinition ist. Grundsätzlich haben Sie 4 Optionen:

  • keine Wirkung (tut nichts)
  • CASCADE (löscht das Kind aswell)
  • NULL SET (setzt das Referenzfeld auf null)
  • SET DEFAULT (setzt die Referenzfeld auf den Standardwert)

Ein Beispiel wäre:

CREATE TABLE parent (
    id INT NOT NULL, 
    PRIMARY KEY (id) 
) ENGINE=INNODB; 

CREATE TABLE child (
    id INT, 
    parent_id INT, 
    INDEX par_ind (parent_id), 
    FOREIGN KEY (parent_id) 
     REFERENCES parent(id) 
     ON DELETE CASCADE -- replace CASCADE with your choice 
) ENGINE=INNODB; 

(für dieses Beispiel und weitere Informationen hier: http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html)

Wenn Sie jetzt ändern, um Ihre Constraint wollen, müssen Sie zuerst fallen lassen müssen, und eine neue erstellen, wie zum Beispiel:

ALTER TABLE child 
ADD CONSTRAINT fk_name 
FOREIGN KEY (parent_id) 
REFERENCES parent(id) 
ON DELETE CASCADE; -- replace CASCADE with your choice 

Ich hoffe das hat geholfen. Außerdem sollten Sie darüber nachdenken, Ihre Eltern nicht wirklich zu löschen und stattdessen eine andere boolesche Spalte "deleted" zu erstellen, die Sie mit "yes" füllen, wenn jemand auf delete klickt. In der "Select" -Abfrage filtern Sie dann nach dieser "gelöschten" Spalte. Der Vorteil ist, dass Sie den Verlauf dieses Eintrags nicht verlieren.

+0

Es ist nicht möglich, alle untergeordneten Tabellen zu löschen. Ich möchte einen Code oder einen Stored Proc, der jederzeit wieder ausgeführt werden kann. –

+0

Ich bin mir nicht sicher, ob Sie das richtig verstanden haben. Sie lassen keine Tabellen fallen, Sie lassen nur die Fremdschlüsseleinschränkung fallen und ersetzen sie durch etwas, das sich so verhält, wie Sie es wollen. Zuerst müssen Sie wissen, wie Ihr Referenzfeld in der Child-Tabelle aussehen soll. Wenn Sie mit einer fehlerhaften Referenz zufrieden sind, tun Sie "No Action". Wenn Sie auch Childs löschen möchten, wenn ein Parent gelöscht wird, wählen Sie "Cascade", wenn Sie es für History-Zwecke behalten möchten, können Sie es auf "Set NULL" setzen, wenn Sie es durch etwas anderes ersetzen wollen, und dann verwenden "Standard festlegen". Sie "verlieren" nur die Referenz und nicht die Kinddaten – chickahoona

+0

@varunkumardutta: Bitte Frage aktualisieren – TheGameiswar

0

Ihr Problem ist das: Eine FK-Einschränkung soll verhindern, dass Sie einen verwaisten Child-Datensatz in einer der 52 Tabellen erstellen. Ich kann Ihnen das gesuchte Skript zur Verfügung stellen, aber Sie müssen zuerst feststellen, dass, wenn Sie versuchen, die FK-Einschränkungen wieder zu aktivieren, die Einschränkungen aufgrund der verwaisten Daten (die die FK-Einschränkungen verhindern sollen) nicht wieder aktiviert werden können. Für den nächsten Schritt müssen die verwaisten Daten in jedem der 52 Tabellen zuerst gelöscht werden. Es ist eigentlich viel einfacher, die Einschränkungen nur mit ON DELETE CASCADE zu wiederholen oder die Einschränkungen zu löschen und die referenzielle Integrität insgesamt zu vergessen. Du kannst es nicht auf beide Arten haben.

Verwandte Themen