SQL ON DELETE CASCADE


Exemple

Supposons que vous ayez une application qui administre des salles.
Supposons en outre que votre application fonctionne par client (locataire).
Vous avez plusieurs clients.
Votre base de données contiendra donc une table pour les clients et une pour les salles.

Maintenant, chaque client a N chambres.

Cela devrait signifier que vous avez une clé étrangère sur votre table de salle, référençant la table client.

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

En supposant qu'un client passe à un autre logiciel, vous devrez supprimer ses données dans votre logiciel. Mais si tu le fais

DELETE FROM T_Client WHERE CLI_ID = x 

Ensuite, vous obtenez une violation de clé étrangère, car vous ne pouvez pas supprimer le client lorsqu'il dispose encore de salles.

Désormais, votre application contient du code d'écriture qui supprime les pièces du client avant de supprimer le client. Supposons encore qu'à l'avenir, de nombreuses dépendances de clés étrangères seront ajoutées à votre base de données, car les fonctionnalités de votre application se développent. Horrible. Pour toute modification de votre base de données, vous devrez adapter le code de votre application à N endroits. Vous devrez peut-être également adapter le code dans d'autres applications (par exemple, interfaces avec d'autres systèmes).

Il y a une meilleure solution que de le faire dans votre code.
Vous pouvez simplement ajouter ON DELETE CASCADE à votre clé étrangère.

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 

Maintenant vous pouvez dire

DELETE FROM T_Client WHERE CLI_ID = x 

et les pièces sont automatiquement supprimées lorsque le client est supprimé.
Problème résolu - sans modification du code d'application.

Un mot d'avertissement: dans Microsoft SQL-Server, cela ne fonctionnera pas si vous avez une table qui fait référence à elle-même. Donc, si vous essayez de définir une cascade de suppression sur une arborescence récursive, comme ceci:

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

cela ne fonctionnera pas, car Microsoft-SQL-server ne vous permet pas de définir une clé étrangère avec ON DELETE CASCADE sur une arborescence récursive. Une des raisons à cela est que l'arbre est probablement cyclique et que cela pourrait conduire à une impasse.

PostgreSQL peut en revanche faire cela;
la condition est que l'arbre soit non cyclique.
Si l'arbre est cyclique, vous obtenez une erreur d'exécution.
Dans ce cas, vous devrez simplement implémenter la fonction de suppression vous-même.

Un mot d'avertissement:
Cela signifie que vous ne pouvez plus simplement supprimer et réinsérer la table client, car si vous faites cela, elle supprimera toutes les entrées dans "T_Room" ... (plus de mises à jour non-delta)