Wie verwende ich Cascade Delete mit SQL Server?

332

Ich habe 2 Tabellen: T1 und T2, es sind vorhandene Tabellen mit Daten. Wir haben eine Eins-zu-Viele-Beziehung zwischen T1 und T2. Wie ändere ich die Tabellendefinitionen, um ein kaskadierendes Löschen in SQL Server durchzuführen, wenn ein Datensatz aus T1 gelöscht wird? Alle zugeordneten Datensätze in T2 werden ebenfalls gelöscht.

Die fremde Beschränkung besteht zwischen ihnen. Ich möchte die Tabellen nicht löschen oder einen Trigger erstellen, um das Löschen für T2 durchzuführen. Wenn ich beispielsweise einen Mitarbeiter lösche, sollte auch der gesamte Überprüfungsdatensatz verschwunden sein.

T1 - Mitarbeiter,

Employee ID      
Name
Status

T2 - Leistungsbeurteilungen,

Employee ID - 2009 Review
Employee ID - 2010 Review
Bichvan Nguyen
quelle

Antworten:

362

Du wirst brauchen,

  • Löschen Sie die vorhandene Fremdschlüsseleinschränkung.
  • Fügen Sie eine neue mit ON DELETE CASCADEaktivierter Einstellung hinzu.

Etwas wie:

ALTER TABLE dbo.T2
   DROP CONSTRAINT FK_T1_T2   -- or whatever it's called

ALTER TABLE dbo.T2
   ADD CONSTRAINT FK_T1_T2_Cascade
   FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE
marc_s
quelle
3
Mein Team und ich haben das einfach gemacht. Wir mussten unsere Einschränkungen fallen lassen und sie erneut hinzufügen. Das hat bei uns funktioniert.
Daniel L. VanDenBosch
2
Wie ist das für ein hartes Löschen? Ein sanftes Löschen hätte niemals ein Problem mit Einschränkungen. Scheint mir das Gegenteil zu sein.
Maxx
2
@Maxx Beim harten Löschen löschen Sie einen Datensatz und müssen sich nicht um verwaiste Register kümmern, während Sie beim weichen Löschen dies manuell tun müssen.
Ronaldo Araújo Alves
318

So fügen Sie einem vorhandenen Fremdschlüssel in SQL Server Management Studio "Cascade delete" hinzu:

Wählen Sie zunächst Ihren Fremdschlüssel aus und öffnen Sie ihn in einem neuen Abfragefenster mit "DROP and Create To ..".

Geben Sie hier die Bildbeschreibung ein

Fügen Sie dann einfach ON DELETE CASCADEden ADD CONSTRAINTBefehl hinzu:

n Klicken Sie auf die Schaltfläche "Ausführen", um diese Abfrage auszuführen.

Übrigens, um eine Liste Ihrer Fremdschlüssel zu erhalten und zu sehen, bei welchen "Kaskadenlöschung" aktiviert ist, können Sie dieses Skript ausführen:

SELECT 
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
   delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1

Und wenn Sie jemals feststellen, dass Sie DROPaufgrund einer Fremdschlüsseleinschränkung keine bestimmte Tabelle finden können , aber nicht herausfinden können, welche FK das Problem verursacht, können Sie diesen Befehl ausführen:

sp_help 'TableName'

Die SQL in diesem Artikel listet alle FKs auf, die auf eine bestimmte Tabelle verweisen.

Hoffe das alles hilft.

Entschuldigung für den langen Finger. Ich habe nur versucht, einen Punkt zu machen.

Mike Gledhill
quelle
163

Sie können dies mit SQL Server Management Studio tun.

→ Klicken Sie mit der rechten Maustaste auf das Tabellendesign, gehen Sie zu Beziehungen und wählen Sie den Fremdschlüssel im linken Bereich und im rechten Bereich aus, erweitern Sie das Menü "INSERT and UPDATE-Spezifikation" und wählen Sie "Cascade" als Delete Rule.

SQL Server Management Studio

Palanikumar
quelle
Hallo, was ist der Unterschied zwischen den 4, macht das Einschalten der Kaskade das Löschen aller Daten in einer Tabelle einfach. Wie kann ich alle Abhängigkeiten / fk-Schlüssel in dieser Tabelle anzeigen , nicht in dieser Tabelle ? Selbst nach dem Löschen aller
FKs erhalte
@aggie - Sie können die Abhängigkeiten überprüfen, indem Sie - mit der rechten Maustaste auf die Tabelle klicken -> "Abhängigkeiten anzeigen". Auch SQL Server gibt Ihnen den detaillierten Fehler mit dem Tabellennamen und dem Spaltennamen wie folgt aus. "Die DELETE-Anweisung steht in Konflikt mit der REFERENCE-Einschränkung" FK_Child1_Parent1 ". Der Konflikt trat in der Datenbank "TESTDB", Tabelle "dbo.Child1", Spalte 'Parent1ID' auf. "
Palanikumar
@aggie - Auch der vierte Fall "Standard festlegen" ist: Sie müssen die Standardbeschränkung in der Spalte Fremdschlüssel festlegen. Wenn wir das übergeordnete Element löschen, wird der Standardwert in untergeordneten Tabellen ersetzt. (Hinweis: Der Standardwert muss mit der übergeordneten Tabelle übereinstimmen.) Weitere Informationen finden Sie unter mssqltips.com/sqlservertip/2365/…
Palanikumar
Das ist sehr hilfreich. Ich frage mich, warum es keine Einfügeregel gibt. Mit anderen Worten, wenn ich T1 eine Zeile hinzufüge, möchte ich, dass der entsprechende Eintrag in T2 automatisch erstellt wird.
Robert M.
@ RobertM. Weil das keinen Sinn macht. Wie würde es wissen, welche Werte einzufügen sind? Möglicherweise können Sie INSERT-Trigger verwenden, um die untergeordneten Zeilen zu generieren. Versuchen Sie, dies zu untersuchen.
Dan Bechard
46

Verwenden Sie so etwas wie

ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;

Geben Sie die richtigen Spaltennamen ein und Sie sollten eingestellt sein. Wie mit mark_s richtig angegeben, müssen Sie möglicherweise zuerst die alte löschen und dann die neue erstellen, wenn bereits eine Fremdschlüsseleinschränkung vorhanden ist.

Hyperboreus
quelle
41
@marc_s - tatsächlich können Sie einen zweiten Fremdschlüssel für genau dieselben Spalten auf beiden Seiten hinzufügen, und er funktioniert ordnungsgemäß. Wenn Sie in einer Produktionsumgebung ohne Ausfallzeiten arbeiten, ist es möglicherweise vorzuziehen, den neuen FK mit Kaskade einzuführen und dann den älteren FK zu löschen, anstatt ein Fenster auf dem Tisch zu lassen, wenn kein FK vorhanden ist. (Gerade auf SQL 2008 getestet)
Damien_The_Unbeliever
Das ist richtig. Ich habe es versucht und es funktioniert. Es ist nicht erforderlich, die ersten Fremdschlüsseleinschränkungen zu löschen. Danke für die Antwort.
Bichvan Nguyen
15

Aktivieren Sie zuerst die ONCascade-Eigenschaft:

1.Löschen Sie die vorhandene Fremdschlüsseleinschränkung

2. Fügen Sie eine neue mit aktivierter Einstellung ON DELETE CASCADE hinzu

Ex:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 

ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

Zweitens, um die ONCascade-Eigenschaft zu deaktivieren:

1.Löschen Sie die vorhandene Fremdschlüsseleinschränkung

2. Fügen Sie eine neue hinzu, wobei die Einstellung ON DELETE NO ACTION aktiviert ist

Ex:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION 
END
Ravula Sandeep
quelle
15

ON DELETE CASCADE
Es gibt an, dass die untergeordneten Daten gelöscht werden, wenn die übergeordneten Daten gelöscht werden.

CREATE TABLE products
( product_id INT PRIMARY KEY,
  product_name VARCHAR(50) NOT NULL,
  category VARCHAR(25)
);

CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
  product_id INT NOT NULL,
  quantity INT,
  min_level INT,
  max_level INT,
  CONSTRAINT fk_inv_product_id
    FOREIGN KEY (product_id)
    REFERENCES products (product_id)
    ON DELETE CASCADE
);

Für diesen Fremdschlüssel haben wir die ON DELETE CASCADEKlausel angegeben , die SQL Server anweist, die entsprechenden Datensätze in der untergeordneten Tabelle zu löschen, wenn die Daten in der übergeordneten Tabelle gelöscht werden. Wenn in diesem Beispiel ein Wert für product_id aus der Produkttabelle gelöscht wird, werden auch die entsprechenden Datensätze in der Inventartabelle gelöscht, die diese product_id verwenden.

Md Shahriar
quelle
-2

Wenn die Eins-zu-Viele-Beziehung von T1 zu T2 ist, stellt sie keine Funktion dar und kann daher nicht zum Ableiten oder Ableiten einer Umkehrfunktion verwendet werden, die garantiert, dass der resultierende T2-Wert keine deduktiv gültigen Tupel von T1 Join T2 auslässt , weil es keine deduktiv gültige Umkehrfunktion gibt. (Die Darstellung von Funktionen war der Zweck von Primärschlüsseln.) Die Antwort in SQL lautet: Ja, Sie können dies tun. Die Antwort im relationalen Denken ist nein, Sie können es nicht tun. Siehe Mehrdeutigkeitspunkte in Codd 1970. Die Beziehung müsste von T1 zu T2 viele zu eins sein.

frank e
quelle
-10

Ich denke, Sie können nicht einfach die Eigenschaft tables löschen. Wenn es sich um tatsächliche Produktionsdaten handelt, löschen Sie einfach den Inhalt, der das Tabellenschema nicht beeinflusst.

Apple Lover
quelle