3つのテーブル間の循環依存(循環参照)を回避するにはどうすればよいですか?


10

3つのテーブルがあります。

  • 役職
  • いいね

ERモデルを設計すると、循環依存関係が発生します。

         1:N
人-------- <投稿

         1:N
投稿---------- <いいね

         1:N
人-------- <いいね

ロジックは次のとおりです。

  • 1人が多くの投稿を持つことができます。

  • 1件の投稿に多くの高評価があります。

  • 1人が多くの投稿を高く評価できます(作成された人は自分の投稿を高く評価できません)。

この種類の循環設計を削除するにはどうすればよいですか?それとも私のdb設計は間違っていますか?

回答:


10

ビジネスルール

あなたが提示したビジネスルールをいくつか言い換えましょう:

  • A Person0-one-or-manyを 作成しますPosts
  • A Post0-one-or-many を受け取りますLikes
  • Personマニフェストは、ゼロ一又は多 LikesWICHのそれぞれに関連する一つの特定の Post

論理モデル

次に、そのような一連のアサーションから、図1に示す2つの論理レベルIDEF1X [1]データモデルを導出しました。

図1-人と投稿のデータモデル

オプションA

あなたはオプションAモデルで見ることができるように、PersonId 移行[2]からPersonPost、それは受信FOREIGN KEY(FK)としてロール名[3]のをAuthorId一緒に、この属性がアップになりPostNumber、PRIMARY KEY(PK)Postエンティティタイプ。

Likeは特定のに関連してのみ存在できると想定しているPostため、とのLike3つの異なる属性で構成されるPKを設定しました。組み合わせとを適切な参照になりFKでPKを。次に、との適切な関連付けを確立するFKです。PostAuthorIdPostNumberLikerIdPostAuthorIdPostNumberPostLikerIdPerson.PersonId

この構造を利用して、決定された人がLike同じPostインスタンスに対して1つの発生のみを明示できることを保証します。

投稿者が自分の投稿を好きにならないようにする方法

人が自分の作成した投稿を気に入ってしまう可能性を許容したくないので、実装フェーズに入るLike.PostAuthorIdLike.LikerId、すべてのINSERT試行のの値との値を比較するメソッドを確立する必要があります。上記の値が一致する場合は、(a)挿入を拒否し、一致しない場合は(b)プロセスを続行させます。

データベースでこのタスクを実行するには、以下を利用できます。

  1. CHECK CONSTRAINTしかし、もちろん、この方法で除外のMySQL、あなたが見ることができるように、それは、これまでのところ、このプラットフォームでは実装されていないので、ここここ

  2. ACIDトランザクション内のコード行

  3. TRIGGER内のコード行。ルール違反の試行を示すカスタムメッセージを返す可能性があります。

オプションB

著者が主な方法でビジネスドメインの投稿を識別する属性でない場合は、オプションBに示したものと同様の構造を使用できます。

このアプローチは、投稿が同じ人によって一度だけ高く評価されることも保証します。


ノート

1.情報モデリングの統合定義(IDEF1X)は、1993年12月に米国国立標準技術研究所(NIST)によって標準として定義された、非常に推奨されるデータモデリング手法です。

2. IDEF1Xは、キーの移行を「親エンティティまたはジェネリックエンティティの主キーを子またはカテゴリエンティティに外部キーとして配置するモデリングプロセス」と定義しています

3. ロール名は、対応するエンティティタイプのコンテキストでそのような属性の意味を表すために、外部キー属性に割り当てられる表記です。ロールの命名は、1970年以来、EF Codd博士による「大規模な共有データバンクのデータのリレーショナルモデル」という独創的な論文で推奨されています。一方、IDEF1X(忠実に保つことはリレーショナルプラクティスを尊重する)もこの手順を支持しています。


6

ここで循環しているものは何もありません。投稿があり、これらのエンティティ間には2つの独立した関係があります。私はこれらの関係の1つを実装することを好むと思います。

  • 人は多くの投稿を書くことができ、投稿は一人で書かれます: 1:n
  • 人は多くの投稿を高く評価でき、投稿は多くの人が高く評価できます:n:m
    n:m関係は別の関係で実装できます:likes

基本的な実装

PostgreSQLでは、基本的な実装は次のようになります

CREATE TABLE person (
  person_id serial PRIMARY KEY
, person    text NOT NULL
);

CREATE TABLE post (
  post_id   serial PRIMARY KEY
, author_id int NOT NULL  -- cannot be anonymous
     REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE  -- 1:n relationship
, post      text NOT NULL
);

CREATE TABLE likes (  -- n:m relationship
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE
, PRIMARY KEY (post_id, person_id)
);

特に、投稿に著者(NOT NULL)が必要ですが、いいの存在はオプションです。既存の同類のために、しかし、postperson しなければならないの両方によって強制(参照することがPRIMARY KEY両方の列を作ることNOT NULLに自動的に(あなたがそう匿名好きでも不可能です)重複し、明示的にこれらの制約を追加することができます。

n:m実装の詳細:

自己ライクを防ぐ

あなたも書いた:

(作成された人は自分の投稿を好きではありません)。

それは、上記の実装ではまだ強制されていません。トリガーを使用できます。
または、これらのより高速で信頼性の高いソリューションの1つ:

コストに対して堅実

それがために必要がある場合堅実、あなたはからFKを拡張することができlikespost含めるようにauthor_id冗長を。次に、単純なCHECK制約で近親相姦を除外できます。

CREATE TABLE likes (
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int 
, author_id int NOT NULL
, CONSTRAINT likes_pkey PRIMARY KEY (post_id, person_id)
, CONSTRAINT likes_post_fkey FOREIGN KEY (author_id, post_id)
     REFERENCES post(author_id, post_id) ON UPDATE CASCADE ON DELETE CASCADE
, CONSTRAINT no_self_like CHECK (person_id <> author_id)
);

これに、そうでなければ冗長なUNIQUE制約が必要ですpost

ALTER TABLE post ADD CONSTRAINT post_for_fk_uni UNIQUE (author_id, post_id);

私はそれをしている間author_id最初に有用なインデックス提供することにしました。

詳細と関連する回答:

CHECK制約付きで安価

上記の「基本的な実装」に基づいています。

CHECK制約は不変であることを意味します。チェックのために他のテーブルを参照することは決して不変ではありません。ここではコンセプトを少し乱用しています。それNOT VALIDを適切に反映するために制約を宣言することをお勧めします。詳細:

CHECKポストの著者が変化しない属性のように思えるので制約は、この特定の場合には、合理的なようです。確実にそのフィールドへの更新を禁止します。

関数を偽造IMMUTABLEます。

CREATE OR REPLACE FUNCTION f_author_id_of_post(_post_id int)
  RETURNS int AS
'SELECT p.author_id FROM public.post p WHERE p.post_id = $1'
LANGUAGE sql IMMUTABLE;

'public'をテーブルの実際のスキーマに置き換えます。
この関数をCHECK制約で使用します。

ALTER TABLE likes ADD CONSTRAINT no_self_like_chk
   CHECK (f_author_id_of_post(post_id) <> person_id) NOT VALID;

4

あなたはあなたのビジネスルールをどのように述べているのか、これを理解するのが難しいと思います。

人と投稿は「オブジェクト」です。動詞です。

実際には2つのアクションがあります。

  1. 人は1つ以上の投稿を作成できます
  2. 多くの人が多くの投稿を好きになることができます。(最後の2つのステートメントの編集)

投稿図のような人

「いいね」テーブルには、主キーとしてperson_idとpost_idがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.