6

2 つのエンティティ間に親子関係があるスキーマがあります。これは一対多なので、当然次のように実装されます。

table Parents
  id

table Children
  id
  parent_id

ただし、子の 1 つを特別なケースとして扱う必要もあります (「昇格した」子と呼びましょう)。これを行うには、次のようないくつかの方法が考えられます。

に属性を付けるだけですChildren

table Parents
  id

table Children
  id
  parent_id
  is_promoted

データベースが一貫性を保証できないという点で、明らかに欠陥があります(少なくとも通常の外部キー制約では)

Parentsテーブルに外部キーを作成します。

table Parents
  id
  promoted_child_id

table Children
  id
  parent_id

これは私の最初の傾向でしたが、循環依存という明らかな欠点があるため、おそらく最適ではありません。

Children私が考えることができる別のオプションは、テーブルに2番目の外部キーを置くことです:

table Parents
  id

table Children
  id
  parent_id
  promoted_parent_id

これにより、一意のインデックスを配置できるため、データベースの一貫性が確保されます。これに関する 1 つの問題は、親 A の子が親 B の昇格としてリストされるという、無意味な関係を持つ可能性があることです。

私が考えることができる最後のオプションは、中間テーブルを作成することです。

table Parents
  id

table Children
  id

table ParentChildRelationship
  parent_id
  child_id
  is_promoted

繰り返しになりますが、parent_id+is_promotedに対して一意の制約を宣言して、一貫性を確保できます。関係を完全なエンティティに昇格させるのはやり過ぎのように思えるので、私はこれについて少し曖昧ですis_promoted.

この問題を処理する標準的な方法について、あなたがどう考えるか知りたいです。特に私はRailsを使っているので、何が最も現実的な解決策であるかに影響するかもしれません。

4

2 に答える 2

2

私はレールの経験はありませんが、1対多の関係のデフォルト値を処理するときに同様のことに遭遇し、通常、dbスキーマに対して次のようなものを使用しました。

table Parents
  id

table Children
  id
  parent_id
  FK (parent_id) references Parents(id)

table PromotedChildren
  child_id
  parent_id
  FK (child_id, parent_id) references Children(id, parent_id)
  UNIQUE Key parent_id

編集

これに答えた後、なぜ私が他の表現よりもこの表現を好むのかを考えるようになったので、もう少し調査を行い、もう少し考えました:

table Parents
  id

table Children
  id
  parent_id
  is_promoted

Jefによって提案された(parent_id、is_promoted)に一意の制約があるこれは、Kelvinによって提案されたように、nullがdbによって無視される場合に機能し、適切なオプションになる可能性があります。ただし、false / 0の代わりにnullを使用することは、nullの誤った使用法であり、フィールドを事実上トライステート、つまり1、0、不明に変えると主張する人もいるかもしれません。また、(parent_id、is_promoted)はスーパーキーではないため、ドメインキーの正規形に違反します。

table Parents
  id
  promoted_child_id

table Children
  id
  parent_id

ご指摘のとおり、これによりサイクルが発生する可能性があり、promoted_child_idをChildren(id)を参照するFKにすることで、ParentAがParentBの子を昇格としてリストするデータベース異常のリスクがあります。

table Parents
  id

table Children
  id
  parent_id
  promoted_parent_id

ここでは、説明したように異常のリスクがあります。Promoted_pa​​rent_idの一意キーも、nullを無視するdbに依存する必要があります。複数のカスケードパス。Promoted_pa​​rent_idとparent_idの冗長性は同じである必要があります。parent_idがpromoted_pa​​rent_idと一致しない異常を更新します。

table Parents
  id

table Children
  id

table ParentChildRelationship
  parent_id
  child_id
  is_promoted

これは、親から子への多対多の表現のように見えます。上記の他の問題と同様の問題が発生します。

Rails開発で最も実用的なものについては、私には言えません。私が提案した表現と、C#とPHPを使用したJefの表現の両方を使用しましたが、実際には違いに気づいていません。

于 2013-01-03T11:18:31.127 に答える
1

parent_idと列の両方に一意の制約を適用して、is_promoted整合性を確保し、言及した他の2つのソリューションの欠点を回避できます。クエリ時にも非常にうまく機能するはずです。

于 2013-01-03T18:33:46.663 に答える