2009-12-17 4 views
0

J'ai deux tables appelées TableA et TableB.Suppression de plusieurs enregistrements de deux tables

TableA a les champs suivants:

TableA_ID 
FileName 

TableB a les champs suivants:

TableB_ID 
TableA_ID 
CreationDate 

Il existe un lien clé étrangère entre les deux tables sur le terrain TableA_ID

J'ai besoin pour supprimer les enregistrements des deux tables. Je dois regarder le "CreationDate" sur la TableB et si c'est après une certaine date, supprimer cet enregistrement. Je devrai également supprimer l'enregistrement dans la TableA avec le même TableA_ID que l'enregistrement dans la TableB

Il peut y avoir plusieurs enregistrements dans la TableB qui utilisent le TableA_ID (une relation de un à plusieurs). Je ne peux donc pas supprimer l'enregistrement dans la TableA si les entrées de la TableB l'utilisent encore. Je sais que cela ne peut pas être fait dans une seule déclaration, mais je suis heureux de le faire dans une transaction. Le problème que j'ai est que je ne suis pas sûr de savoir comment faire cela. J'utilise MS SQL Server 2008. Je ne veux pas utiliser de triggers si possible.

Répondre

5

Peut-il y avoir des enregistrements dans TableA sans enregistrement correspondant dans TableB? Sinon, nous savons après que nous supprimons de TableB, nous pouvons supprimer tous les enregistrements qui ne correspondent pas à TableA:

begin transaction 
delete from TableB 
where CreationDate > @SomeDate 

delete from TableA 
where TableA_ID not in (select TableA_ID from TableB) 
end transaction 

Sinon:

begin transaction 
-- Save the TableA_IDs being deleted: 
select distinct TableA_ID 
into #TableA_Delete 
from Table_B 
where CreationDate > @Somedate 

-- Depending on the expected size of #TableA_Delete, you may want 
-- to create an index here, to speed up the delete from TableA. 

delete from TableB 
where CreationDate > @SomeDate 

delete from TableA 
where TableA_id in (select TableA_Id from #TableA_Delete) 
and TableA_id not in (select TableA_id from TableB) 
commit transaction 

NOTE Les deux solutions ci-dessus doivent remettre d'erreur ajouté.

Voir également NYSystemsAnalyst pour une autre méthode de stockage temporaire des ID.

+0

+1 La solution de Shannon résout la lacune de la clause WHERE ... GROUP BY dans ma solution ci-dessous. – NYSystemsAnalyst

+0

Pour une raison quelconque, cette opération échoue en raison de la dernière instruction "Where". Je vais jouer avec, mais quelqu'un peut-il repérer s'il manque quelque chose? – Retrocoder

+0

@Retrocoder: Désolé, ce dernier endroit où il a été laissé en vrac et pas utile. Edité pour réparer. –

0

L'intégrité référentielle doit supprimer les lignes enfant lorsque le parent est supprimé. Assurez-vous que les suppressions en cascade sont activées.

Sinon, vous devez mettre deux instructions de suppression, une pour les enregistrements enfants et une pour l'enregistrement parent.

DELETE FROM TableB INNER JOIN TableA ON TableA.TableAID = TableB.TableAID WHERE CreationDate >= SomeDate 

DELETE FROM TableA WHERE TableAID=SomeID 
+1

Il ne peut pas dépendre des cascades référentielles DELETE parce qu'il ne veut pas supprimer les entrées de la tableB si elles sont CreationDate est OK. Une suppression en cascade les éliminerait. En outre, les deux instructions que vous avez postées suppriment les entrées correctes de TableB, mais d'où vient SomeID? – NYSystemsAnalyst

+0

SomeID est juste un paramètre. Je suppose qu'il/elle a une sorte d'idée de ce que les paramètres sont en SQL. – JonH

+0

De plus, il existe de nombreuses raisons de ne pas utiliser la suppression en cascade. Il est préférable de ne pas pouvoir le configurer car cela peut créer de graves problèmes de performances. – HLGEM

0

Edit: Désolé, je ne vois pas la partie de votre question en indiquant la nécessité de conserver les entrées tableA si elles ont plusieurs enregistrements dans TableB. Utilisez-le à la place:

Vous devez placer tout cela dans une transaction pour garantir l'intégrité des données.

+0

La sélection qui remplit @ID ne fonctionnera pas. 1) OP ne dit rien sur le fait qu'il n'y ait pas plusieurs lignes dans TableB qui sont supprimées par TableA_ID.2) La clause HAVING arrive (logiquement) après la clause WHERE, donc si des enregistrements TableB ne sont pas supprimés, la clause HAVING ne les verra pas, et ne les comptera pas. –

+0

1) Le message d'origine indique "Il peut y avoir plusieurs enregistrements dans TableB qui utilisent TableA_ID (une relation un à plusieurs) .Je ne peux donc pas supprimer l'enregistrement dans TableA si les entrées dans TableB l'utilisent encore." Ainsi, les enregistrements TableA ne peuvent pas être supprimés s'il existe des entrées dans la table B qui ne sont pas supprimées. – NYSystemsAnalyst

Questions connexes