私は次のように定義された非常に単純なデータベースを持っています。
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
から削除されdbo.PostTagJunction
。しかし、孤児にもかかわらず、 dbo.Tags
hello-world
記録は残っています。タグも削除したいどうやって?
私は、タグが別の投稿によって使用されている場合、それを削除してはならないことを強調する必要があります。ありがとうございました。
Dapper
とC#
を使ってデータベースと通信しています。
カスケードオプションを使用して子テーブルレコードを削除して親テーブルレコードを削除することはできません。 C#アプリケーションから渡すPostSlug ( @PostSlug
)に基づいてPosts, Tags, PostTagJunction
をパラメータとして削除する新しいストアドプロシージャを作成します。
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
お役に立てれば。
トリガーを使用してデータベースを非正規化することができます。つまり、 dbo.Posts
でFOR DELETE
トリガーを作成すると、孤立したdbo.Tags
テーブルのレコードが自動的に削除されます。例:
CREATE TRIGGER triggerName
ON dbo.Posts
FOR DELETE
AS
DELETE FROM dbo.Tags
WHERE TagName IN (SELECT TagName FROM DELETED)
GO