Il est possible de supprimer à l'aide d'instructions de jointure pour qualifier l'ensemble à supprimer, par exemple:
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')
Toutefois, je suis intéressé par la suppression des deux côtés des critères de jointure - 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 permettent de créer plusieurs chemins en cascade.
Idéalement, j'aimerais quelque chose comme:
DELETE J, U
FROM Users U
inner join LinkingTable J on U.id = J.U_id
...
Syntaxiquement, cela ne marche pas, mais je suis curieux de savoir si une telle chose est possible.
Non, vous devez exécuter plusieurs déclarations.
Puisque vous devez supprimer de deux tables, envisagez de créer une table temporaire avec les identifiants correspondants:
SELECT U.Id INTO #RecordsToDelete
FROM Users U
JOIN LinkingTable J ON U.Id = J.U_Id
...
Et puis supprimez de chacune des tables:
DELETE FROM Users
WHERE Id IN (SELECT Id FROM #RecordsToDelete)
DELETE FROM LinkingTable
WHERE Id IN (SELECT Id FROM #RecordsToDelete)
La façon dont vous dites est possible dans MY SQL
mais pas pour SQL SERVER
Vous pouvez utiliser la pseudo-table "supprimé" pour supprimer les valeurs de deux tables à la fois, par exemple:
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 à ceci Link
et connaître l'utilisation de la table supprimée, vous pouvez suivre ceci Utiliser les tables insérées et supprimées
Le seul moyen auquel je puisse penser est de casser logiquement les clés étrangères bidirectionnelles d'une manière procédurale.
Cette approche peut avoir un impact considérable sur votre application si vous ne disposez pas d'indicateurs pour visualization
state ou status
.
Quelque chose comme
INSERT
lignes factices non visibles pour les utilisateurs (avec quelque chose comme Id = -1
pour les valeurs factices)Ajoutez à LinkingTable
une colonne alternative pour renvoyer à Users
, je l'appellerai U_ComesFrom
ALTER TABLE LinkingTagble ADD U_ComesFrom_U_id INT DEFAULT (-1)
Ajouter FOREIGN KEY
avec une NOCHECK
ALTER TABLE LinkingTable AVEC NOCHECK
FOREIGN KEY (U_ComesFrom_U_id)
RÉFÉRENCES Utilisateurs (Id);
Ajouter à la colonne Users
ALTER TABLE Utilisateurs AJOUTER MarkedForDeletion BIT NOT NULL DEFAULT (0)
Ensuite, 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 les performances puisque chaque transaction représenterait au moins 4 opérations DML par clé bidirectionnelle.
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 Store pour celle-ci Utilisation de la procédure stockée avec transaction:
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;