2010-02-09 4 views
1

Ok. J'ai essayé le déclencheur, mais ça n'a pas marché.Besoin de changer ma structure SQL pour suppression

Je Cascades de A à Linker et de B à Linker, Cascade des Utilisateurs à A, aucune action de l'utilisateur B.

Mon déclencheur est sur les utilisateurs et est la suivante:

set ANSI_NULLS ON set quoted_identifier go ALTER TRIGGER [trig_delUser] ON [dbo] [aspnet_Users] POUR SUPPRIMER AS SET NOCOUNT ON. DE SUPPRIMER B OU B.UserId = Deleted.UserId

je reçois l'exception: L'instruction DELETE en conflit avec la contrainte de référence "FK_B_aspnet_Users"

Je travaille avec une version modifiée aspnetdb base de données SQL:

[schéma partiel DB] [2]

Je suppression en cascade sur la relation B_Linker et la relation et il A_Linker ne pas s eem à être un danger de cycles se produisant.

Lorsque je supprime un utilisateur, je voudrais que tous A entrées et les entrées B à supprimer ainsi que tout éditeur de liens associés entrées; malheureusement, SQL mgmt studio me permettra seulement de mettre une cascade supprimer la règle sur SOIT aspnet_Users_A ou aspnet_Users_B, pas les deux.

Que dois-je faire?

Merci beaucoup.

[2]: http://i48.tinypic.com/2nsnc3k.png

Répondre

0

C'est l'une des limitations malheureuses et franchement plutôt ennuyeuses de SQL Server.

Ce n'est pas le fait qu'il peut y avoir des cycles qui pose problème, c'est simplement comme l'indique l'erreur - vous avez plusieurs chemins en cascade vers la table Linker. Le premier est aspnet_Users -> A -> Linker et le second est aspnet_Users -> B -> Linker.

Vous n'avez vraiment deux choix:

  • Choisissez un chemin pour mettre en œuvre la CASCADE et réglez l'autre NO ACTION. Ensuite, écrivez une procédure stockée qui supprime les entités enfants non en cascade avant de supprimer les entités parent afin d'empêcher une erreur de clé étrangère. Ou, ne faites pas CASCADE non plus et demandez à votre SP de faire la cascade pour les deux.

  • N'ajoutez aucune clé étrangère à la seconde relation; À la place, utilisez un déclencheur FOR DELETE sur le parent pour supprimer les entités enfants.Je n'aime pas beaucoup utiliser les déclencheurs pour RI, mais ce n'est pas beaucoup pire que la première option. À certains égards, c'est mieux, car les clients de base de données n'ont pas à s'inquiéter de votre implémentation spécifique des relations FK.

Ni l'un ni l'autre ne sont idéaux, mais il n'y a pas d'autre solution parfaite que de changer votre conception. S'il vous est possible de modifier votre schéma de telle sorte que vous ayez plusieurs chemins en cascade, ce serait la meilleure chose à faire - mais je reconnais qu'il y a (beaucoup) de situations réelles où cela n'est pas possible . Ne sachant pas les spécificités de votre schéma, je ne peux pas dire avec certitude si oui ou non il y a un design plus optimal.

+0

Je dois également pouvoir supprimer des entrées de A ou B, en supprimant les entrées Linker associées en même temps. Aurai-je besoin d'un proc/trigger pour ça aussi? –

+0

@KR: En utilisant l'approche SP, oui. En utilisant l'approche de déclenchement, vous pouvez créer le déclencheur * seulement * sur A ou B; SQL Server ne se plaindra pas d'une relation en cascade de 'aspnet_Users' à la fois' A' et 'B' tant qu'au moins l'un d'eux n'a pas la cascade de' Linker'. – Aaronaught

+0

Ok. J'ai essayé le déclencheur, mais ça n'a pas marché. Je Cascades de A à Linker et de B à Linker, Cascade des Utilisateurs à A, aucune action de l'utilisateur à B. Mon déclenchement est sur les utilisateurs et est la suivante: ANSI_NULLS fixés SUR set quoted_identifier aller ALTER TRIGGER [trig_delUser] ON [dbo] [aspnet_Users] POUR SUPPRIMER AS SET NOCOUNT ON. DE SUPPRIMER B OU B.UserId = Deleted.UserId Je reçois l'exception: L'instruction DELETE en conflit avec la contrainte de référence « FK_B_aspnet_Users » –

-1

Il vous suffit de mettre les ON DELETE CASCADE règles sur les clés étrangères.

+0

Comme je l'ai mentionné, j'ai essayé, mais SQL managenet studio ne me laisse pas. –

0

Je ne mettrais pas en œuvre cette suppression en cascade. Ou par un déclencheur. Que se passerait-il si quelqu'un devait supprimer 40 000 enregistrements en même temps. Vous verrouillez le parent et toutes les tables enfant, éventuellement pendant des minutes, voire des heures, pendant qu'il se déroule et que c'est le cas.

Donc vraiment ce que vous devriez faire est d'écrire les suppressions dans les tables enfant d'abord, puis la suppression de la table parent et les mettre dans une transaction. Cela fonctionnera assez bien lorsque vous supprimez un enregistrement à la fois. Les grandes suppressions doivent être écrites séparément (ne pas boucler le proc existant) et sont un autre sujet, mais au moins maintenant vous pouvez les faire sans tuer votre serveur.

+0

A et B ne contiendront jamais que 10 à 15 entrées pour chaque utilisateur, donc je pense qu'un déclencheur est assez sûr, mais je le garderai à l'esprit pour l'avenir, merci. –

Questions connexes