web-dev-qa-db-ja.com

同じPRIMARYテーブルをターゲットとするSET NULLを持つ2つのFOREIGN KEY制約

ここに明らかな何かが欠けているように感じます...

プライマリテーブル(Peopleと呼びましょう)とセカンダリテーブル(Groupsと呼びましょう)があり、2つの異なる役割(SecretaryTreasurer)。これらの列は両方ともintであり、People.IDに戻るFKです。

CREATE TABLE People(
ID int NOT NULL,
FullName varchar(50) NOT NULL,
CONSTRAINT [PK_People] PRIMARY KEY CLUSTERED (ID ASC))

CREATE TABLE Groups(
ID int NOT NULL,
Treasurer int NULL,
Secretary int NULL,
CONSTRAINT PK_Groups PRIMARY KEY CLUSTERED (ID ASC))

ここまでは順調ですね。しかし、ロールはオプション(null可能)なので、Personを削除し、グループのFK値をNULLに設定できるようにしたいと思います。

ALTER TABLE dbo.Groups ADD CONSTRAINT FK_Groups_Treasurer FOREIGN KEY (Treasurer) REFERENCES dbo.People (ID) ON DELETE SET NULL

ALTER TABLE dbo.Groups ADD CONSTRAINT FK_Groups_Secretary FOREIGN KEY (Secretary) REFERENCES dbo.People (ID) ON DELETE SET NULL

今問題があります:

テーブル 'Groups'にFOREIGN KEY制約 'FK_Groups_Secretary'を導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります。

ここでの問題は何ですか?なぜSQL Serverは気にするのですか?起こり得るカスケードの競合は何ですか? Personを削除する場合、関連するテーブルのFK値をNULLに設定します。これは、それぞれがFKを持つ2つの異なるテーブルに対しては問題ありません。ただし、同じテーブルに2つのFK値を含めることは禁止されているようです。

何か不足していますか?これはどういうわけか悪いデザインですか?この状況に対処する正しい方法は何ですか?それは一般的なユースケースのようです。

1
Neil Laslett

カスケード削除が行われているように見え、理論的には別のグループで財務担当者または秘書として参照される可能性のある誰かを削除することになります。

グループテーブルが第1正規形に違反しています。これは、アドレス1、アドレス2をテーブルに持つのと同じです。

Groupid、person id、およびroleidを保持する3番目のテーブルGroupPersonRoleが必要です。

1つのテーブルで個人を定義します。別のテーブルでグループを定義します。そして、別のテーブルで役割を定義します。次に、4番目に、GroupPersonRoleと言います。これらを組み合わせて、必要に応じてFKを描画できます。

誰かがさらにグループの役割を追加したい場合はどうなりますか?誰かが新しいアイデアを得るたびにスキーマを変更する必要はありません。

1
user238855