Comment utiliser la suppression en cascade avec SQL Server?

332

J'ai 2 tableaux: T1 et T2, ce sont des tableaux existants avec des données. Nous avons une relation un à plusieurs entre T1 et T2. Comment puis-je modifier les définitions de table pour effectuer la suppression en cascade dans SQL Server lorsqu'un enregistrement de T1 est supprimé, tous les enregistrements associés dans T2 sont également supprimés.

La contrainte étrangère est en place entre eux. Je ne veux pas supprimer les tables ou créer un déclencheur pour effectuer la suppression de T2. Par exemple, lorsque je supprime un employé, tous les enregistrements de révision doivent également disparaître.

T1 - Employé,

Employee ID      
Name
Status

T2 - Examens des performances,

Employee ID - 2009 Review
Employee ID - 2010 Review
Bichvan Nguyen
la source

Réponses:

362

Tu devras,

  • Supprimez la contrainte de clé étrangère existante,
  • Ajoutez-en un nouveau avec le ON DELETE CASCADEparamètre activé.

Quelque chose comme:

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
la source
3
Mon équipe et moi venons de le faire. Nous avons dû abandonner nos contraintes et les rajouter. Cela a fonctionné pour nous.
Daniel L. VanDenBosch
2
Comment est-ce en faveur d'une suppression définitive? Une suppression logicielle n'aurait jamais de problème de contrainte. Cela me semble tout à fait le contraire.
Maxx
2
@Maxx Dans la suppression matérielle, vous supprimez un enregistrement et vous n'avez pas à vous soucier des registres orphelins, tandis que dans la suppression logicielle, vous devez le faire manuellement.
Ronaldo Araújo Alves
319

Pour ajouter "Suppression en cascade" à une clé étrangère existante dans SQL Server Management Studio:

Tout d'abord, sélectionnez votre clé étrangère et ouvrez-la "DROP and Create To .." dans une nouvelle fenêtre de requête.

entrez la description de l'image ici

Ensuite, ajoutez simplement ON DELETE CASCADEà la ADD CONSTRAINTcommande:

n Et appuyez sur le bouton "Exécuter" pour exécuter cette requête.

Soit dit en passant, pour obtenir une liste de vos clés étrangères et voir celles pour lesquelles la «suppression en cascade» est activée, vous pouvez exécuter ce script:

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

Et si jamais vous trouvez que vous ne pouvez pas DROPune table particulière en raison d'une contrainte de clé étrangère, mais que vous ne pouvez pas déterminer quel FK est à l'origine du problème, vous pouvez exécuter cette commande:

sp_help 'TableName'

Le SQL de cet article répertorie tous les FK qui font référence à une table particulière.

J'espère que tout cela vous aidera.

Toutes mes excuses pour le doigt long. J'essayais juste de faire un point.

Mike Gledhill
la source
163

Vous pouvez le faire avec SQL Server Management Studio.

→ Cliquez avec le bouton droit sur la conception de la table et accédez à Relations et choisissez la clé étrangère dans le volet gauche et dans le volet droit, développez le menu "INSÉRER et METTRE À JOUR la spécification" et sélectionnez "Cascade" comme règle de suppression.

SQL Server Management Studio

Palanikumar
la source
salut, quelle est la différence entre les 4, l'activation de la cascade facilite la suppression de toutes les données d'une table. Comment puis-je afficher toutes les dépendances / clés fk sur cette table, pas à partir de cette table. Même après avoir supprimé tous les FK, j'obtiens toujours une erreur
aggie
@aggie - Vous pouvez vérifier les dépendances par - Faites un clic droit sur la table -> "Afficher les dépendances" Le serveur SQL vous donnera également l'erreur détaillée avec le nom de la table et le nom de la colonne comme ceci "L'instruction DELETE est en conflit avec la contrainte REFERENCE" FK_Child1_Parent1 ". Le conflit s'est produit dans la base de données "TESTDB", table "dbo.Child1", colonne 'Parent1ID'. "
Palanikumar
@aggie - Le 4ème cas "Définir par défaut" est également: vous devez définir la contrainte par défaut dans la colonne Clé étrangère, lorsque nous supprimons le parent, la valeur par défaut sera remplacée dans les tables enfants. (Remarque: la valeur par défaut doit correspondre à la table parent.) Pour plus d'informations, visitez mssqltips.com/sqlservertip/2365/…
Palanikumar
C'est très utile. Je me demande, pourquoi n'y a-t-il pas de règle d'insertion? En d'autres termes, lorsque j'ajoute une ligne à T1, je souhaite que l'entrée correspondante dans T2 soit créée automatiquement.
Robert M.
@RobertM. Parce que cela n'a aucun sens. Comment pourrait-il savoir quelles valeurs INSÉRER? Vous pourrez peut-être utiliser les déclencheurs INSERT pour générer les lignes enfants, essayez de rechercher cela.
Dan Bechard
47

Utilisez quelque chose comme

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

Remplissez les noms de colonne corrects et vous devriez être défini. Comme mark_s l'a correctement indiqué, si vous avez déjà une contrainte de clé étrangère en place, vous devrez peut-être d'abord supprimer l'ancienne, puis créer la nouvelle.

Hyperboreus
la source
41
@marc_s - en fait, vous pouvez ajouter une deuxième clé étrangère contre exactement les mêmes colonnes des deux côtés, et cela fonctionnera correctement. Si vous travaillez dans un environnement de production sans temps d'arrêt, il peut être préférable d'introduire le nouveau FK avec cascade, puis de supprimer l'ancien FK, plutôt que de laisser une fenêtre sur la table quand aucun FK n'est en place. (Juste testé sur SQL 2008)
Damien_The_Unbeliever
C'est correct. J'ai essayé ça, et ça marche. Il n'est pas nécessaire de supprimer les premières contraintes de clé étrangère. Merci pour la réponse.
Bichvan Nguyen
15

Tout d'abord pour activer la propriété ONCascade:

1.Drop la contrainte de clé étrangère existante

2. ajoutez un nouveau avec le paramètre ON DELETE CASCADE activé

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

Deuxième propriété à désactiver ONCascade:

1.Drop la contrainte de clé étrangère existante

2.Ajouter un nouveau avec le paramètre ON DELETE NO ACTION activé

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
la source
15

ON DELETE CASCADE
Il spécifie que les données enfants sont supprimées lorsque les données parent sont supprimées.

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
);

Pour cette clé étrangère, nous avons spécifié la ON DELETE CASCADEclause qui indique à SQL Server de supprimer les enregistrements correspondants dans la table enfant lorsque les données de la table parent sont supprimées. Ainsi, dans cet exemple, si une valeur product_id est supprimée de la table products, les enregistrements correspondants dans la table d'inventaire qui utilisent ce product_id seront également supprimés.

Md Shahriar
la source
-2

Si la relation un à plusieurs va de T1 à T2, alors elle ne représente pas une fonction et ne peut donc pas être utilisée pour déduire ou déduire une fonction inverse qui garantit que la valeur T2 résultante n'omet pas des tuples de T1 joignant T2 qui sont déductivement valides , car il n'y a pas de fonction inverse valablement déductible. (représenter les fonctions était le but des clés primaires.) La réponse dans SQL pense que oui, vous pouvez le faire. La réponse dans la pensée relationnelle est non, vous ne pouvez pas le faire. Voir les points d'ambiguïté dans Codd 1970. La relation devrait être multiple de T1 à T2.

franc e
la source
-10

Je pense que vous ne pouvez pas simplement supprimer la propriété des tables et s'il s'agit de données de production réelles, supprimez simplement le contenu qui n'affecte pas le schéma de la table.

Amateur de pomme
la source