高级级联删除

时间:2015-02-23 07:28:05

标签: c# sql sql-server tsql dapper

我有一个非常简单的数据库,其架构定义如下:

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

我想这样做,以便当我从dbo.Posts删除帖子时,dbo.Tags中生成的未引用标签也会被删除。

请考虑以下代码:

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'

由于我使用了级联删除选项,因此该帖子已从dbo.Posts中移除,并且该记录已从dbo.PostTagJunction中删除。但是,尽管是孤儿,但hello-world中的dbo.Tags记录仍然存在。我也想删除标签。怎么样?

我应该强调,如果标签被其他帖子使用,则应该被删除。谢谢。

我正在使用DapperC#与数据库进行通信。

2 个答案:

答案 0 :(得分:3)

您可以使用触发器对数据库进行非规范化,换句话说,您可以在FOR DELETE上创建dbo.Posts触发器,它会自动删除孤立dbo.Tags表中的记录,例如:< / p>

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

答案 1 :(得分:2)

通过使用级联选项删除子表记录,无法删除父表记录。创建一个新的存储过程,以基于从C#application作为参数传递的 PostSlug Posts, Tags, PostTagJunction)删除@PostSlug

删除PostTagJunction表中的级联约束并尝试类似这样的内容。

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

希望这有帮助。