5

Person テーブルと Belonging テーブルの 2 つのテーブルがある 1 対多の関係があるとします。現在、各個人はお気に入りの所有物を 1 つだけ持っており、特定の所有物を別の人の所有物にすることはできません。

私の質問は、その情報をどこに保管するのがよいでしょうか? Person テーブルで favorite_belonging_id として、または Belonging テーブルで is_favorite エントリとして ? 私の目には、最初の選択肢がより良いバージョンのように見えますが、SQL に詳しい人々がそれについて何を言わなければならないかを聞きたいと思います。

EDIT : 人には多くの持ち物がありますが、お気に入りの持ち物は 1 つだけで、各持ち物は 1 人の人にしか所属できません。これは 1 対多の関連付けです。

4

7 に答える 7

3

favourite_belonging_id最初の提案(テーブルの列)を使用して、テーブル内のからへPersonの外部キー参照を作成できるようにしたいと思います。(person_id, favourite_belonging_id)(owner_id, belonging_id)Belonging

is_favouriteテーブルにフラグを作成する別のルートを使用する場合Belonging、人とお気に入りの帰属関係の1:1の性質を保証する明確な方法はありません(人が複数の持ち物を持っている場合、複合UNIQUEインデックスは失敗します。(owner_id, is_favourite)彼らのお気に入り)。

とはいえ、この情報は実際には人の所有物ではなく、の所有物であるため、実際にはテーブルに含まているようには感じられません。あなたがそれについて強く感じているなら、あなたは(または)インデックスを持つテーブルを作成することができます。PersonBelongingFavouritesUNIQUEPRIMARYperson_id

于 2012-07-07T19:03:21.903 に答える
2

基本人物とは何の関係もないため、個人テーブルには属しません。

所属するテーブルしかない場合-これにはperson_idもあると思いますが、これは所属と人の間の関係を表現する場所であり、修飾子も行くべき場所です。

別のオプションは、2 つをリンクする中央に 3 番目のテーブルを配置することです。この場合、お気に入りのフラグはそこに移動します。

編集:デザインの私の好みは、3番目のテーブルオプションです-ここでは、開始日と終了日、およびお気に入りのフラグを設定できます-これにより、理論的には、ある時点で別の人の所有物を取引し、それでも知ることができますどうした。

于 2012-07-07T18:48:53.340 に答える
1

以下は、お気に入りの持ち物にフラグを立てる、やや型破りな方法を提供するため、最良のオプションではない場合があります。ただし、利点は、この方法では循環参照のないテーブルが2つだけになり、すべての人がお気に入りの持ち物を1つだけ持つことが保証されることです。

つまり、people(またはpersons)との2つのテーブルbelongingsです。peopleテーブルの構造は次のとおりです。

person_id INT AUTO_INCREMENT,
other columns as necessary,

PRIMARY KEY (person_id)

belongingsテーブルは次のように作成されます。

belonging_id INT AUTO_INCREMENT,
person_id    INT NOT NULL,
is_favourite enum ('1'),
other columns as necessary,

PRIMARY KEY (belonging_id),
FOREIGN KEY (person_id) REFERENCING people (person_id),
UNIQUE (person_id, is_favourite)

重要な要素は、単一の可能な値でis_favouritenull許容型として宣言することです。enumこのように、のペアで一意性制約を宣言する場合、一意性制約は少なくとも1つのメンバーがnullである行を無視するため、同じで空(null)(person_id, is_favourite)の行をできるだけ多く持つことができます。また、一意の制約に違反するためを使用して複数を作成することはできません。person_idis_favouriteperson_idis_favourite = '1'

于 2012-07-07T21:26:28.373 に答える
1

ない。person_favourite_belonging私の提案は、次のように別のテーブルを追加することです。

CREATE TABLE person
( person_id INTEGER NOT NULL
--- various other columns about Persons
, PRIMARY KEY (person_id)
) ;

CREATE TABLE belonging
( belonging_id INTEGER NOT NULL 
, person_id INTEGER NOT NULL 
--- various other columns about Belongings
, PRIMARY KEY (belonging_id)
, UNIQUE KEY (person_id, belonging_id)       --- this Unique constraint is needed
, FOREIGN KEY (person_id)
    REFERENCES person (person_id)
) ;

CREATE TABLE person_favourite_belonging
( person_id INTEGER NOT NULL 
, belonging_id INTEGER NOT NULL
, PRIMARY KEY (person_id)
, FOREIGN KEY (person_id, belonging_id)      --- for this Foreign Key constraint
    REFERENCES belonging (person_id, belonging_id)
) ;

これは、これを行うための私の好みの方法です。代替手段があり、すべてに長所と短所があります。このアプローチの長所は次のとおりです。

  • 外部キー制約に循環パスがない (したがって):
  • 人物、持ち物、またはお気に入りの持ち物を挿入、削除、または更新する際に鶏が先か卵が先かという問題はありません。
  • すべての外部キー列は NOT NULL として定義できます。
  • 整合性は、データベース レベルで適用できます。
  • 要件が変更され、1 人あたり 2 つ (またはそれ以上) のお気に入りが必要な場合は、お気に入りテーブルの制約のみを適切に変更します。

この質問の私の回答も確認してください (ほぼ同じ問題があります): In SQL, is it OK for two tables to refer to each other?

于 2012-07-07T21:38:58.800 に答える
1

さまざまなオプションのほとんどすべてがすでにさまざまな回答でレイアウトされていることがわかりますが、すべてにコメントして、あなたがすべきだと思うことについて私の印象を与えるのではなく、自分で回答を作成します.

システムがどのように機能するかを私がどのように理解しているかを明確にするために: すべてのユーザーは複数の持ち物を持つことができますが、どの持ち物も 1 人だけが助けることができます。

この場合、所有物を個人に結び付けることができる所有物テーブルに user_id を持つことが最も理にかなっています。user_id が設定されると、他の誰もそれを要求できなくなります。

さて、「お気に入り」の部分に関しては、できることがいくつかあります。本当に最善の方法は、実行する予定のクエリに大きく依存します。JOIN テーブルを追加することを検討する人もいますが、正直なところ、これはかなり無意味な追加データです。ユーザーテーブルと同じ量の行がそこにある可能性が高く、それを別のテーブルに入れることで、できないことがたくさんあります(たとえば、お気に入りを持っていない人の数を確認します) . 同様に、JOIN テーブルは user_belonging 関係には意味がありません。所属とそれを持つことができる人数の間には 1 対 1 の関係があるからです。
したがって、2 つの実行可能なオプションがあると思います。所有物テーブルにフィールド (/switch) を追加して、ユーザーの所有物がお気に入りであることを示すか、ユーザー テーブルにフィールドを追加して、どの所有物がユーザーのお気に入りであるかを示します。個人的には後者が最もメリットがあると思いますが、実行するクエリによっては、前者の方が理にかなっている場合があります。全体として、最大の違いは、物事を挿入前に処理するか、選択後に処理するかです。たとえば、後者の場合、ユーザーがすでにお気に入りを持っているかどうかを調べるために、独立したクエリを実行する必要があります (前者の場合、ユーザー テーブルのフィールドに一意のインデックスを配置するため、これは必要ありません)。 、

私が自分自身を明確に説明したかどうか、またはさらに質問がある場合はお知らせください。

于 2012-07-07T19:25:28.470 に答える
0

favourite_thing は所属テーブルへの FK です (そのテーブルが存在する場合、そうでない場合はドメインである可能性があります) が、追加の制約で、persons テーブルの所属 ID を一意にすることができます。

アップデート:

DROP table belonging;
CREATE table belonging
        ( id INTEGER PRIMARY KEY
        , description varchar
        );

DROP table person;
CREATE table person
        ( id INTEGER PRIMARY KEY
        , description varchar
        , favourite_thing INTEGER REFERENCES belonging (id)
        );

-- Now add the unique constraint
-- NOTE: favourite_thing can still be NULL
ALTER TABLE person
        ADD CONSTRAINT must_be_unique UNIQUE (favourite_thing)
        ;

更新 2: すべての所有物が正確に 1 人の人に属している場合、所有者フィールドを所有物に追加できます。

CREATE table belonging
        ( id INTEGER PRIMARY KEY
        , owner_id INTEGER NOT NULL REFERENCES person(id)
        , description varchar
        );

DROP table person CASCADE;
CREATE table person
        ( id INTEGER PRIMARY KEY
        , description varchar
        , favourite_thing INTEGER REFERENCES belonging (id)
        );

ALTER TABLE person
        ADD CONSTRAINT must_be_unique UNIQUE (favourite_thing)
        ;
于 2012-07-07T18:52:01.700 に答える
-1

実際、あなたは 1 対 1 の関係を示しています。1.それを Person テーブルに保持します。2. Belonging テーブルに保持します。3. 両方で保持します。4. 別のテーブルで開催します。

于 2012-07-07T18:47:47.600 に答える