4

次の列 CAT_ID (BIGINT) NAME (VARCHAR) PARENT_CAT_ID (BIGINT) を持つ、CATEGORY という名前のテーブルで ON DELETE CASCADE を実行する必要があります。

PARENT_CAT_ID は CAT_ID の FK です。明らかに、素敵な SQL Server では、削除への循環または複数のパスを主張する ON DELETE CASCADE を使用できません。

よく提案される解決策はトリガーです。次のトリガーを作成しました。

USE [ma]
GO
/****** Object:  Trigger [dbo].[TRG_DELETE_CHILD_CATEGORIES]    Script Date: 11/23/2009 16:47:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRG_DELETE_CHILD_CATEGORIES] ON [dbo].[CATEGORY] FOR DELETE AS
SET NOCOUNT ON
/* * CASCADE DELETES TO '[Tbl B]' */
DELETE CATEGORY FROM deleted, CATEGORY WHERE deleted.CAT_ID = CATEGORY.PARENT_CAT_ID

子カテゴリを持つカテゴリを手動で削除すると、次の例外が発生します。

例外

トリガーの何が問題なのですか?

更新: 編集して申し訳ありませんが、別のテーブル CAT_SCH.ID の FK である別の列 CATEGORY.CAT_SCH_ID があります。この FK には CASCADE DELETE もあります。つまり、CAT_SCH を削除すると、その CATEGORies も削除する必要があります。したがって、トリガーを定義すると、次のエラーが発生します。

テーブル 'CATEGORY' に INSTEAD OF DELETE または INSTEAD OF UPDATE TRIGGER 'TRG_DEL_CATEGORY_WITH_CHILDREN' を作成できません。これは、テーブルにカスケード DELETE または UPDATE を持つ FOREIGN KEY があるためです。

何か案は?

4

1 に答える 1

12

FOR DELETE トリガーは、元の DELETE が実行された後に発生します。再帰的に削除するには、INSTEAD OF DELETE トリガーを記述する必要があります。

アルゴリズムは次のようになります。

  • 削除された PK を一時テーブルに挿入する

  • 一時テーブル内のレコードの詳細レコードを検索

  • レコードがなくなるまでループ

一時テーブルと結合して、テーブル内のレコードを削除します。

ブログで再帰的削除について説明しました。

アップデート

カテゴリの再帰的な外部キーから ON DELETE CASCADE フラグを削除するだけでよいと思います。CAT_SCH からの外部キーの CASCADE フラグは重要ではありません。

于 2009-11-23T15:22:04.413 に答える