Eliminación de cascada avanzada

c# dapper sql sql-server tsql

Pregunta

Tengo una base de datos muy simple cuyo esquema se define de la siguiente manera:

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)
);

Quiero hacerlo de modo que cuando elimine una publicación de dbo.Posts que las etiquetas resultantes no referenciadas en dbo.Tags también se eliminen.

Considera el siguiente código:

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'

Como utilizo la opción de eliminación en cascada, la publicación se elimina de dbo.Posts y el registro se elimina de dbo.PostTagJunction . Sin embargo, a pesar de ser huérfano, el registro de hello-world en dbo.Tags permanece. Quiero borrar la etiqueta también ¿Cómo?

Que debería hace hincapié en que si la etiqueta está siendo utilizado por otro post, no debería ser borrado. Gracias.

Estoy usando Dapper y C# para comunicarme con la base de datos.

Respuesta aceptada

No es posible eliminar los registros de tabla padre eliminando los registros de tabla hijo usando la opción de cascada. Cree un nuevo procedimiento almacenado para eliminar los Posts, Tags, PostTagJunction basados ​​en PostSlug ( @PostSlug ) pasando de la aplicación C # como parámetro.

PostTagJunction la restricción en cascada en la tabla PostTagJunction y pruebe algo como esto.

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

Espero que esto ayude.


Respuesta popular

Puede desnormalizar su base de datos usando un desencadenador, en otras palabras, puede crear un desencadenador FOR DELETE en dbo.Posts que borrará automáticamente su registro en una tabla dbo.Tags huérfana, por ejemplo:

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


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué