SQL
Cascading Delete
Suche…
ON DELETE CASCADE
Angenommen, Sie haben eine Anwendung, die Räume verwaltet.
Nehmen Sie weiter an, dass Ihre Anwendung pro Mandant (Mandant) ausgeführt wird.
Sie haben mehrere Kunden.
Ihre Datenbank enthält also eine Tabelle für Kunden und eine für Räume.
Nun hat jeder Kunde N Räume.
Dies bedeutet, dass Sie einen Fremdschlüssel in Ihrer Zimmertabelle haben, der auf die Client-Tabelle verweist.
ALTER TABLE dbo.T_Room WITH CHECK ADD CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
GO
Vorausgesetzt, ein Client wechselt zu einer anderen Software, müssen Sie seine Daten in Ihrer Software löschen. Aber wenn du es tust
DELETE FROM T_Client WHERE CLI_ID = x
Sie erhalten dann eine Verletzung des Fremdschlüssels, da Sie den Client nicht löschen können, wenn er noch über Räume verfügt.
Jetzt haben Sie Code in Ihre Anwendung geschrieben, der die Räume des Kunden löscht, bevor der Client gelöscht wird. Nehmen Sie weiterhin an, dass in der Datenbank in Zukunft viele weitere Fremdschlüsselabhängigkeiten hinzugefügt werden, da die Funktionalität Ihrer Anwendung erweitert wird. Schrecklich. Für jede Änderung in Ihrer Datenbank müssen Sie den Code Ihrer Anwendung in N Stellen anpassen. Möglicherweise müssen Sie den Code auch in anderen Anwendungen anpassen (z. B. Schnittstellen zu anderen Systemen).
Es gibt eine bessere Lösung als im Code.
Sie können ON DELETE CASCADE
einfach zu Ihrem Fremdschlüssel hinzufügen.
ALTER TABLE dbo.T_Room -- WITH CHECK -- SQL-Server can specify WITH CHECK/WITH NOCHECK
ADD CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
ON DELETE CASCADE
Jetzt kannst du sagen
DELETE FROM T_Client WHERE CLI_ID = x
und die Räume werden automatisch gelöscht, wenn der Client gelöscht wird.
Problem gelöst - ohne Änderung des Anwendungscodes.
Ein Wort zur Vorsicht: In Microsoft SQL-Server funktioniert dies nicht, wenn Sie eine Tabelle haben, die auf sich selbst verweist. Wenn Sie also versuchen, eine Löschkaskade in einer rekursiven Baumstruktur zu definieren, gehen Sie wie folgt vor:
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation] WITH CHECK ADD CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation] FOREIGN KEY([NA_NA_UID])
REFERENCES [dbo].[T_FMS_Navigation] ([NA_UID])
ON DELETE CASCADE
GO
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation] CHECK CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation]
GO
Es funktioniert nicht, da der Microsoft-SQL-Server es nicht zulässt, einen Fremdschlüssel mit ON DELETE CASCADE
in einer rekursiven Baumstruktur festzulegen. Ein Grund dafür ist, dass der Baum möglicherweise zyklisch ist und dies möglicherweise zu einem Deadlock führt.
PostgreSQL dagegen kann dies tun;
Voraussetzung ist, dass der Baum nicht zyklisch ist.
Wenn der Baum zyklisch ist, wird ein Laufzeitfehler angezeigt.
In diesem Fall müssen Sie die Löschfunktion nur selbst implementieren.
Ein Wort der Warnung:
Das bedeutet, dass Sie die Client-Tabelle nicht mehr einfach löschen und erneut einfügen können. Wenn Sie dies tun, werden alle Einträge in "T_Room" gelöscht. ...