別の方法(Nullなし、およびFOREIGN KEY
リレーションシップ内のサイクルなし)は、「お気に入りの子」を格納する3番目のテーブルを持つことです。ほとんどのDBMSでは、に追加のUNIQUE
制約が必要TableB
です。
@Aaronは、上記の命名規則がかなり面倒であり、エラーにつながる可能性があることを特定するのが迅速でした。Id
テーブル全体に列がなく、表示される多くのテーブルで列(結合されている)が同じ名前である場合、通常は良いです(正気を保ちます)。だから、ここに名前の変更があります:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
UNIQUE (ParentID, ChildID)
FavoriteChild
ParentID INT NOT NULL PRIMARY KEY
ChildID INT NOT NULL
FOREIGN KEY (ParentID, ChildID)
REFERENCES Child (ParentID, ChildID)
(使用している)SQL-Serverには、IsFavorite
言及したビット列のオプションもあります。親ごとに一意のお気に入りの子は、フィルター処理された一意のインデックスを介して実現できます。
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
IsFavorite BIT NOT NULL
CREATE UNIQUE INDEX is_FavoriteChild
ON Child (ParentID)
WHERE IsFavorite = 1 ;
そして、少なくともSQL-Serverではオプション1が推奨されない主な理由は、外部キー参照の循環パスのパターンにいくつかの問題があることです。
かなり古い記事「SQL By Design:The Circular Reference」を読んでください。
2つのテーブルの行を挿入または削除すると、「鶏と卵」の問題が発生します。制約に違反せずに、最初にどのテーブルを挿入する必要がありますか?
これを解決するには、少なくとも1つの列をNULL可能に定義する必要があります。(OK、技術的にあなたは、あなたがすべての列を持つことができますする必要はありませんとしてNOT NULL
だけ遅延可能制約を実装している同様の問題のアーウィンの答え@参照のPostgresやOracleなどのDBMS、中:。SQLAlchemyの中に複雑な外部キー制約方法についてこれはPostgresで実行できます)。それでも、このセットアップは薄い氷の上でスケートをするように感じます。
また、SOでほぼ同じ質問を確認してください(ただし、MySQLの場合)SQLでは、2つのテーブルが相互に参照しても問題ありませんか?私の答えはほぼ同じです。ただし、MySQLには部分インデックスがないため、実行可能なオプションはNULL可能FKと追加のテーブルソリューションのみです。