現在、階層データ構造のスキーマを評価しています。私の主な問題は、一貫性のないデータ(別の階層の外部キーの参照)を防ぐためにスキーマをどのように設計するかです。私が発見した2つのバリアントは、複合キーまたは代理キーを使用することです。
要件
この例では、外部キーは複合主キーの一部です。これにより、複合主キーの一部であるため、パーツのタイプが同じアイテム(同じ階層)に割り当てられていることが自動的にチェックされます。
モデルを拡張するのは簡単ではないので、このアプローチは私にとって厄介なようです。たとえば、単一のPartのメタデータを保持するPartMetadataテーブルを作成する場合、全体を含める必要がありますメタデータが階層に接続されていない場合でも、複合キー。
Item
ItemId (PK)
Name
Type
TypeId (PK)
ItemId (PK, FK)
Name
SubItem
SubItemId (PK)
ItemId (PK, FK)
Name
Part
PartId (PK)
ItemId (PK, FK)
SubItemId (PK, FK)
TypeId (PK, FK)
Name
この場合、別のアイテムに属するタイプのパーツを挿入できないようにするために、追加の制約またはトリガーを定義する必要があります。
Item
ItemId (PK)
Name
Type
TypeId (PK)
ItemId (FK)
Name
SubItem
SubItemId (PK)
ItemId (FK)
Name
Part
PartId (PK)
SubItemId (FK)
TypeId (FK)
Name
1番目の設計では、Part
が同じSubItem
に(Type
およびItem
を介して)関連付けられるように強制できます。 2番目の方法ではできません(DDLのみを使用して、前述のトリガーを適用するか、すべてのCRUD操作が制限を処理するストアドプロシージャを介して実行されるようにするためにトリガーが必要です)。そうでない場合、Part
に関連するSubItem
と、異なるType
を参照するItems
が存在する場合があります。
(1番目の)デザインに関する注意事項:
正しいFOREIGN KEY
制約。 Part
の3つの単純なFKで要件を強制することはできませんが、2つの複合FKが必要です。
Part
PartId (PK)
ItemId (PK, FK1, FK2)
SubItemId (PK, FK1)
TypeId (PK, FK2)
Name
PKにPartId
がなくてもかまいません。同じSubItem
と同じType
に属する2つ以上のパーツを持つことはできますか?そうでない場合、一意(または主キー)制約は(ItemId, SubItemId, TypeId)
。はいの場合、それは(ItemId, SubItemId, TypeId, PartId)
、ご存知の通り。
PartMetadata
またはPart
テーブルを参照できるその他のテーブルに関しては、Part
の複合キー全体を含める必要はありません。いつでも、新しいサロゲートUNIQUE
キーをPart
に追加して、代わりに使用できます。これは、エンティティの複雑で高い階層で私が考える一般的な方法です。ある程度までは、複合PKとFKを使用できます。それらが広すぎる場合(4〜6列)、いくつかの重要なテーブルに代理一意キーを追加し、モデルの下位のテーブルからの参照にそれらを使用できます。