サーチ…


カスケードを削除する

部屋を管理するアプリケーションがあるとします。
さらに、アプリケーションがクライアントごとに動作すると仮定します(テナント)。
複数のクライアントがあります。
したがって、データベースにはクライアント用のテーブルとルーム用のテーブルが含まれます。

現在、すべてのクライアントにはN個のルームがあります。

これは、クライアントテーブルを参照して、ルームテーブルに外部キーがあることを意味します。

ALTER TABLE dbo.T_Room  WITH CHECK ADD  CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
GO

クライアントが他のソフトウェアに移動したと仮定すると、ソフトウェア内のデータを削除する必要があります。しかし、もしあなたが

DELETE FROM T_Client WHERE CLI_ID = x 

それで、部屋があるときにクライアントを削除することはできないので、外部キー違反が発生します。

これで、クライアントを削除する前にクライアントルームを削除するコードをアプリケーションに記述することになりました。アプリケーションの機能が拡張されるため、今後さらに多くの外部キー依存関係がデータベースに追加されると想定してください。恐ろしい。データベース内のすべての変更について、アプリケーションのコードをN個所に適用する必要があります。おそらく、他のアプリケーション(例えば、他のシステムとのインターフェース)でもコードを適応させる必要があります。

コード内で行うよりも優れた解決策があります。
外部キーにON DELETE CASCADEを追加することができます。

ALTER TABLE dbo.T_Room  -- WITH CHECK -- SQL-Server can specify WITH CHECK/WITH NOCHECK
ADD  CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID) 
ON DELETE CASCADE 

今あなたは言うことができる

DELETE FROM T_Client WHERE CLI_ID = x 

クライアントが削除されると、部屋は自動的に削除されます。
問題解決 - アプリケーションコードの変更なし。

注意の1つの言葉:Microsoft SQL Serverでは、それ自体を参照するテーブルがある場合、これは機能しません。したがって、次のように、再帰ツリー構造で削除カスケードを定義しようとすると、

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation]  WITH CHECK ADD  CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation] FOREIGN KEY([NA_NA_UID])
REFERENCES [dbo].[T_FMS_Navigation] ([NA_UID]) 
ON DELETE CASCADE 
GO

IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation] CHECK CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation]
GO

Microsoft-SQLサーバーでは、再帰的なツリー構造でON DELETE CASCADEして外部キーを設定することができないため、動作しません。この理由の1つは、ツリーが循環する可能性があり、それがデッドロックにつながる可能性があるということです。

これに対し、PostgreSQLはこれを行うことができます。
木が非周期的であることが要件である。
ツリーが周期的な場合は、実行時エラーが発生します。
その場合は、自分でdelete関数を実装するだけです。

注意の言葉:
つまり、クライアントテーブルを単に削除して再挿入することはできません。これを行うと、「T_Room」...のすべてのエントリが削除されるためです(非デルタ更新はもうなくなります)



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow