Est-il possible de supprimer de plusieurs tables dans la même instruction SQL?

Il est possible de supprimer en utilisant des instructions join pour qualifier l'ensemble à supprimer, comme ce qui suit:

DELETE J
FROM Users U
inner join LinkingTable J on U.id = J.U_id
inner join Groups G on J.G_id = G.id

WHERE G.Name = 'Whatever'
and U.Name not in ('Exclude list')

Cependant, je suis intéressé par la suppression des deux côtés des critères de jointure-à la fois l'enregistrement LinkingTable et l'enregistrement utilisateur dont il dépend. Je ne peux pas activer les cascades car ma solution est D'abord le code Entity Framework et les relations bidirectionnelles créent plusieurs chemins en cascade.

Idéalement, je voudrais quelque chose comme:

DELETE J, U
FROM Users U
inner join LinkingTable J on U.id = J.U_id
...

Syntaxiquement ce n'est pas le cas travailler, mais je suis curieux si quelque chose comme ça est possible?

28
demandé sur Unihedron 2013-07-09 06:54:33

5 réponses

Non, vous devez exécuter plusieurs instructions.

Parce que vous devez supprimer de deux tables, envisagez de créer une table temporaire des ID correspondants:

SELECT U.Id INTO #RecordsToDelete
FROM Users U
   JOIN LinkingTable J ON U.Id = J.U_Id
...

Puis Supprimer de chacune des tables:

DELETE FROM Users 
WHERE Id IN (SELECT Id FROM #RecordsToDelete)

DELETE FROM LinkingTable
WHERE Id IN (SELECT Id FROM #RecordsToDelete)
34
répondu sgeddes 2013-07-09 03:06:17

La façon dont vous dites qu'il est Possible de MY SQL, mais pas pour SQL SERVER

Vous pouvez utiliser la pseudo-table "deleted" pour supprimer les valeurs de deux Tables à la fois comme,

 begin transaction;

 declare @deletedIds table ( samcol1 varchar(25) );

 delete #temp1
 output deleted.samcol1 into @deletedIds
 from #temp1 t1
 join #temp2 t2
 on t2.samcol1 = t1.samcol1

 delete #temp2
 from #temp2 t2
 join @deletedIds d
 on d.samcol1 = t2.samcol1;

 commit transaction;

Pour une brève explication, vous pouvez jeter un oeil à ce lien

Et pour connaître l'utilisation de la Table supprimée, vous pouvez suivre cette en utilisant les Tables insérées et supprimées

3
répondu Rajesh 2017-05-23 12:09:41

La seule façon dont je pouvais penser est de casser logiquement les clés étrangères bidirectionnelles d'une manière procédurale .

Cette approche peut avoir un impact énorme sur votre application si vous n'avez pas d'indicateurs pour visualization state ou status

Quelque Chose comme

  1. INSERT dummy pas de lignes visibles pour les Utilisateurs (avec quelque chose comme Id = -1 pour des valeurs factices)
  2. Ajouter à LinkingTable une colonne alternative pour pointer vers Users, Je l'appellerai U_ComesFrom

    Modifier la TABLE LinkingTagble ajouter U_ComesFrom_U_id INT DEFAULT (-1)

  3. Ajouter FOREIGN KEY avec NOCHECK

    Modifier la table LinkingTable avec NOCHECK
    Clé étrangère (U_ComesFrom_U_id)
    Références utilisateurs (Id);

  4. Ajouter à Users colonne

    Modifier les utilisateurs de la TABLE ajouter MarkedForDeletion BIT NOT NULL DEFAULT (0)

Alors votre SQL ressemblerait à

BEGIN TRANSACTION
    UPDATE J
    SET U_Comes_From_U_id = U_ID, U_id = -1 -- or some N/R value that you define in Users
    FROM Users U
    inner join LinkingTable J on U.id = J.U_id
    inner join Groups G on J.G_id = G.id
    WHERE G.Name = 'Whatever'
    and U.Name not in ('Exclude list')

    UPDATE U
    SET MarkedForDeletion = 1
    FROM Users
    inner join LinkingTable J on U.id = J.U_ComesFrom_U_id 
    WHERE U_id > 0

    DELETE FROM LinkingTable 
    WHERE U_ComesFrom_U_id > 0

    DELETE FROM Users
    WHERE MarkedForDeletion = 1

COMMIT

Cette approche aurait un impact sur la performance puisque chaque transaction serait au moins 4 opérations DML par clés bidirectionnelles.

2
répondu Luis LL 2013-07-09 05:33:01

Utiliser TRY CATCH avec Transaction

BEGIN TRANSACTION
BEGIN TRY
    DELETE from A WHERE id=1

    DELETE FROM b WHERE id=1

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH

Ou vous pouvez également utiliser la procédure de magasin pour même Utilisation De La Procédure Stockée Avec Transaction:

1
répondu uma 2013-07-09 05:56:46

Si vous créez la clé étrangère via T-SQL, vous devez ajouter L'option ON DELETE CASCADE à la clé étrangère:

Code Snippet 

ALTER TABLE <tablename>
ADD CONSTRAINT <constraintname> FOREIGN KEY (<columnname(s)>)
REFERENCES <referencedtablename> (<columnname(s)>)

ON DELETE CASCADE;
1
répondu Nagu 2014-03-31 09:29:40