データモデリング:テーブルに単一のテーブルに制約される複数の外部キーがある場合、優れたリレーショナルデザインとは何ですか?
-
08-07-2019 - |
質問
2つのテーブルがあります。 1.従業員 2.バウチャー
Employeesテーブルには単一の主キーがあります。 バウチャーテーブルには、Employeesテーブルを参照する3つの外部キー制約があります。
以下は、SQL Serverで両方のテーブルとそれらの関係を作成するためのサンプルT-SQLスクリプト(実際のテーブルスクリプトではありません)です。
IF OBJECT_ID('dbo.Vouchers') IS NOT NULL
DROP TABLE dbo.Vouchers
IF OBJECT_ID('dbo.Employees') IS NOT NULL
DROP TABLE dbo.Employees
GO
CREATE TABLE Employees
(
ObjectID INT NOT NULL PRIMARY KEY IDENTITY
)
CREATE TABLE Vouchers
(
ObjectID INT NOT NULL PRIMARY KEY IDENTITY,
IssuedBy INT,
ReceivedBy INT,
ApprovedBy INT,
CONSTRAINT fk_Vouchers_Employees_IssuedBy FOREIGN KEY (IssuedBy)
REFERENCES Employees (ObjectID)
ON UPDATE CASCADE
ON DELETE NO ACTION,
CONSTRAINT fk_Vouchers_Employees_ReceivedBy FOREIGN KEY (ReceivedBy)
REFERENCES Employees (ObjectID)
ON UPDATE CASCADE
ON DELETE NO ACTION,
CONSTRAINT fk_Vouchers_Employees_ApprovedBy FOREIGN KEY (ApprovedBy)
REFERENCES Employees (ObjectID)
ON UPDATE CASCADE
ON DELETE NO ACTION
)
ただし、エラーがスローされます:
Msg 1785, Level 16, State 0, Line 7
Introducing FOREIGN KEY constraint 'fk_Vouchers_Employees_ReceivedBy' on table 'Vouchers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
ここでどのような効率的なソリューションが利用できるのか分かりません。関係の要件は次のとおりです。従業員が削除されるたびに、その列の一部を従業員に参照するバウチャーは削除されません(ON DELETE CASCADEはオプションではありません)。代わりに、削除されたEmployeeを参照している列(IssuedBy、ReceivedBy、ApprovedBy)の値をNULLに設定する必要があります(列がNULLABLEであるため)。
どうもありがとう!
解決
厳密には、リレーショナルデザインの観点から、3つの外部キーとしてのバウチャーテーブル。 CASCADEアサーションなどを使用してそれらを実施することを選択するかどうかは実装上の問題ですが、リレーショナルデザインは依然として存在します。おそらく、3つのフィールドのいずれかがNULLでない場合、一致するレコードが存在する必要があることを強制する必要があります。か否か。これは、設計を強制するかどうかに関する実装上の問題です。
ただし、あなたが説明する違反はあなたの責任で想定されます。この質問をしているという事実は、これらの選択が沼地に至るすべての方法を十分に理解していないかもしれないことを示唆しています。
エラーは、3人のうち2人以上が同じ従業員を参照している可能性があるという事実の結果であると思われます。
ところで、CASCADESが役立つような方法でレコードを削除する必要があることはほとんどありません。通常、データベースが大きくなりすぎるのを防ぐために使用されます。データベースの容量は時間の経過とともに問題になりません。
他のヒント
実際には従業員を削除するのではなく、トリガーを使用してフラグを設定し、従業員を削除済みとしてマークします。
通常、更新または削除のカスケードをオンにしませんが、代わりにこれらのアクションを明示的に実行するアプリケーションが必要です。
設計の観点から、リストした3つの外部キーがあると良いようです。表示されるエラーメッセージは、外部キーのON UPDATE CASCADEオプションに関連しているように見えます(ただし、指定されたとおりにテーブルを作成できました)。とにかく、あなたが望んでいると言う振る舞いを得るには、レコードを削除する前に起動するEmployeesテーブルのトリガーをお勧めします。このトリガーは、バウチャーテーブルでEmployees.OjbectIDのインスタンスを検索し、それらをNULLに設定します。