Suppression en cascade avancée

c# dapper sql sql-server tsql

Question

J'ai une base de données très simple dont le schéma est défini comme suit:

CREATE TABLE dbo.Tags
(
    TagName NVARCHAR(100) PRIMARY KEY
);

CREATE TABLE dbo.Posts
(
    PostSlug NVARCHAR(100) PRIMARY KEY,
    Title NVARCHAR(100) NOT NULL
);

CREATE TABLE dbo.PostTagJunction 
(
    PostSlug NVARCHAR(100),
    TagName  NVARCHAR(100)
    PRIMARY KEY (PostSlug, TagName),
    FOREIGN KEY (PostSlug) REFERENCES dbo.Posts (PostSlug)
        ON DELETE CASCADE,
    FOREIGN KEY (TagName)  REFERENCES dbo.Tags (TagName)
);

Je veux faire en sorte que lorsque je supprime un message de dbo.Posts que les balises non référencées résultant dans dbo.Tags sont également supprimés.

Considérez le code suivant:

INSERT INTO dbo.Posts
    VALUES ('hello-world', 'Hello World');
INSERT INTO dbo.Tags
    VALUES ('Introduction');
INSERT INTO dbo.PostTagJunction
    VALUES ('hello-world', 'Introduction'); 
DELETE 
FROM dbo.Posts
WHERE postslug = 'hello-world'

Étant donné que j'utilise l'option de suppression en cascade, la publication est supprimée de dbo.Posts et l'enregistrement est supprimé de dbo.PostTagJunction . Cependant, en dépit d'être un orphelin, le record hello-world monde dbo.Tags en dbo.Tags reste. Je veux aussi supprimer l'étiquette. Comment?

Je tiens à souligner que si l'étiquette est utilisée par un autre message, elle ne devrait pas être supprimée. Je vous remercie.

J'utilise Dapper et C# pour communiquer avec la base de données.

Réponse acceptée

Il n'est pas possible de supprimer les enregistrements de la table parent en supprimant les enregistrements de la table enfant à l'aide de l'option en cascade. Créez une nouvelle procédure stockée pour supprimer les Posts, Tags, PostTagJunction basés sur le PostSlug ( @PostSlug ) en passant par l'application C # en tant que paramètre.

Supprimez la contrainte en cascade dans la table PostTagJunction et essayez quelque chose comme ça.

DECLARE @PostSlug NVARCHAR(100) = 'hello-world'
DECLARE @TagName NVARCHAR(100) = ''

SELECT @TagName= TagName FROM PostTagJunction WHERE PostSlug =@PostSlug
DELETE PostTagJunction WHERE PostSlug =@PostSlug

IF NOT EXISTS(SELECT 1 FROM PostTagJunction WHERE TagName =@TagName)
DELETE Tags WHERE TagName =@TagName

DELETE Posts WHERE PostSlug =@PostSlug

J'espère que cela t'aides.


Réponse populaire

Vous pouvez dénormaliser votre base de données à l'aide d'un déclencheur. En d'autres termes, vous pouvez créer un déclencheur FOR DELETE sur dbo.Posts qui supprimera automatiquement votre enregistrement dans un tableau orphelin dbo.Tags , par exemple:

CREATE TRIGGER triggerName
    ON dbo.Posts
    FOR DELETE
AS
    DELETE FROM dbo.Tags
    WHERE TagName IN (SELECT TagName FROM DELETED)
GO


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi