2009-08-12 5 views
2

私は同じ結果、すなわちデフォルト/優先値のオプションとm:nの関係を達成すると信じている2つのスキーマを以下に示します。どちらか一方を使用する理由はありますか?あなたが最初に自分の名前を知らなくても、人を追加することはできません2番目のスキーマでm:nを1つの省略可能なデフォルト値でモデリングする方法?

スキーマ#1

CREATE TABLE people (
    id serial, 
    primary key (id) 
); 

CREATE TABLE names (
    id serial, 
    first_name text not null, 
    last_name text not null, 
    primary key (id) 
); 

CREATE TABLE person_has_name (
    person_id integer not null references people (id), 
    name_id integer not null references names (id), 
    is_default boolean not null default false, 
    primary key (person_id, name_id) 
); 

スキーマ#2

CREATE TABLE people (
    id serial, 
    default_name_id integer references names (id), 
    primary key (id) 
); 

-- this table has not changed 
CREATE TABLE names (
    id serial, 
    first_name text not null, 
    last_name text not null, 
    primary key (id) 
); 

CREATE TABLE person_has_name (
     person_id integer not null references people (id), 
     name_id integer not null references names (id), 
     primary key (person_id, name_id) 
); 

答えて

0

。限り、これは大丈夫です(つまり、人が追加されるたびに、彼らは彼らの名前を明らかにする必要があることを知っている)、私はこれらのスキーマのいずれかがうまく、そしてスキーマ#2はデフォルトの名前のみを照会する必要があるシナリオ。

+0

申し訳ありませんが、FKは持つべきではありませんnullでない制約 –

+0

idを追加すると、最初のスキーマperson_has_nameにperson_idごとにdefault = trueが1つだけ存在するように制約が必要になります。この理由とあなたが私がスキーマ#2を好むと述べている理由もあります。 –

+0

しかし、スキーマ#2には独自の問題があります。 person_has_nameテーブルにdefault_name_idも存在するはずですか?それはできない可能性があります。 –

1

さんは分析してみましょう:

  • 2番目のスキーマは、デフォルトとして、複数のnameを設定するためにあなたに防ぐが、デフォルトnameとして、いくつかの関係のない名前を設定するには、あなたに防ぐことはできません。
  • 最初のスキーマでは逆です。

私は(あなたのゾンビユーザーに)あなたに提案する数学の問題解決第三スキーマ:

CREATE TABLE people (
    id serial, 
    default_name_id integer , 
    primary key (id), 
    constraint default_person_name_fk   --<--HERE 
    foreign key (id, default_name_id) 
    references person_has_name (person_id, name_id) 
); 

-- this table has not changed 
CREATE TABLE names (
    id serial, 
    first_name text not null, 
    last_name text not null, 
    primary key (id) 
); 

CREATE TABLE person_has_name (
    person_id integer not null references people (id), 
    name_id integer not null references names (id), 
    primary key (person_id, name_id) 

); 

よろしく及び遅延については申し訳ありません、私は遅れを;)

0

私が使用しますどちらも

解決策1では、人に2つのデフォルト名を付けることを妨げることはありません。

解決策2は、自分の名前ではない既定の名前を持つ人を防御しません。外字キーをdefault_name_id references names(id)から(person_id, default_name_id) references person_has_name(person_id, name_id)に変更することはできますが、循環参照があり、それは解決しにくい別の問題です。

あなたはあなたの第二の溶液に類似し、これを、使用することができます:デフォルトの名前持っているそれらの人々のために、この余分なテーブルで

CREATE TABLE people (
    id serial, 
          --- no default_name_id as foreign key here 
    primary key (id) 
); 

CREATE TABLE names (
    id serial, 
    first_name text not null, 
    last_name text not null, 
    primary key (id) 
); 

CREATE TABLE person_has_name (
    person_id integer not null references people (id), 
    name_id integer not null references names (id), 
    primary key (person_id, name_id) 
); 

CREATE TABLE person_default_name (
    person_id integer not null, 
    name_id integer not null, 
    primary key (person_id), 
    foreign key (person_id, name_id) 
    references person_has_name (person_id, name_id) 
); 
+0

あなたの余分なテーブルは1対1の人々です。このフィールドを余分なテーブルに抽出する理由は何ですか? – danihp

+0

@danihp:はい、それは人々にとって '1:0..1 'です。既定の名前を持つユーザーのみその理由は、テーブル間の循環参照を排除するためです。 –

+0

'default_name_id'をヌル値に設定するか、' people'テーブルと 'people_has_name'テーブルに挿入/削除したいときにchichen-and-eggの問題を処理しても問題はありません。 –

関連する問題