我有一个非常简单的数据库,其架构定义如下:
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
记录仍然存在。我也想删除标签。怎么样?
我应该强调,如果标签被其他帖子使用,则不应该被删除。谢谢。
我正在使用Dapper
和C#
与数据库进行通信。
答案 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
希望这有帮助。