- 顧客が削除されたときに注文が削除されないようにしたい。(カスケードの削除時)
- ID列を使用しているので、OnUpdateCascadeは必要ありません
- 顧客を指す/参照する注文は存在しますが、顧客テーブルを削除できるはずです。他のテーブルの注文テーブルがまだ必要なので、顧客がいついなくなってもかまいません。
On Delete / Update Cascadeで参照整合性を使用しない場合、このシナリオでは外部キーは意味がありますか?
On Delete / Update Cascadeで参照整合性を使用しない場合、このシナリオでは外部キーは意味がありますか?
はい。外部キーは、自分自身をクリーンアップするためだけでなく、主にデータが最初から正しいことを確認するために配置されています(場合によってはオプティマイザーを支援することもできます)。私は至る所で外部キーを使用していますが、カスケードアクションに実装する必要性をまだ見つけていません。カスケードの目的は理解していますが、これらのプロセスを自分で制御する方が常に優れていると感じています。
カスケードの問題を回避できることをすでに説明しようとしましたが(したがって、3番目の条件を満たしています)、図を追加すると思いました。
顧客を削除した後も、注文を残すことができます。重要なのは、Orders.CustomerID
列をnull許容にすることです。
CREATE TABLE dbo.Customers(CustomerID INT PRIMARY KEY);
CREATE TABLE dbo.Orders(OrderID INT PRIMARY KEY, CustomerID INT NULL
FOREIGN KEY REFERENCES dbo.Customers(CustomerID));
Orders.CustomerID
これで、顧客を削除する場合、ストアドプロシージャを介してこれらの操作を制御すると仮定すると、最初に顧客を次のように設定して、この方法で行うことができますNULL
。
CREATE PROCEDURE dbo.Customer_Delete
@CustomerID INT
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Orders SET CustomerID = NULL
WHERE CustomerID = @CustomerID;
DELETE dbo.Customers
WHERE CustomerID = @CustomerID;
END
GO
Customersテーブルからのアドホック削除を制御できない場合でも、トリガーの代わりにこれを実現できます。
CREATE TRIGGER dbo.Cascade_CustomerDelete
ON dbo.Customers
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
UPDATE o SET CustomerID = NULL
FROM dbo.Orders AS o
INNER JOIN deleted AS d
ON o.CustomerID = d.CustomerID;
DELETE c
FROM dbo.Customers AS c
INNER JOIN deleted AS d
ON c.CustomerID = d.CustomerID;
END
GO
とはいえ、顧客を削除して注文を保持する目的(または誰がその注文をしたかについての表示)を理解しているのかどうかはわかりません。
したがって、明確にするために、現在、顧客から注文までのFKがあります。この関係では、カスケードの更新/削除は有効になっていません。あなたの計画は顧客を削除することですが、注文は残しておきます。
これは外部キー制約に違反します。削除が発生しないようにします。制約を無効にした場合は、削除を実行してから再度有効にすると、それを機能させることができます。
ただし、これにより、システムに孤立した注文レコードが残ります。長期的にはサポートが難しくなる可能性があります。これをサポートしなければならない次の男は何を考えますか?
記録を保持し、アクティブ/非アクティブまたは作成済みおよび非アクティブの日付のステータスを追加する方がよいのではないでしょうか。
スペースを減らすためにデータベースの整合性を侵害することに苦労しています...?または、削除する主な理由は何ですか?
アクティブではなくなったレコードを常に除外する必要がない場合は、アクティブな顧客のコレクションを作成するビューまたはパッケージを使用します。すべてではありませんが一部のデータを削除することは、私には間違っているように思われます。