2009-08-12 6 views
2

Unten sind zwei Schemas, von denen ich glaube, dass sie das gleiche Ergebnis ergeben, d. H. Die m: n-Beziehung mit der Option für einen Standard/bevorzugten Wert. Gibt es einen Grund, einen über den anderen zu benutzen?Wie modelliere ich m: n mit einem optionalen Standardwert?

Schema # 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) 
); 

Schema # 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) 
); 

Antwort

0

Mit dem zweiten Schema man die Menschen nicht, ohne vorher zu wissen, ihren Namen hinzufügen kann. Solange dies in Ordnung ist (dh Sie wissen, dass jedes Mal, wenn eine Person hinzugefügt wird, ihren Namen preisgeben müssen), würde ich sagen, dass eines dieser Schemata in Ordnung ist und dass Schema 2 möglicherweise sogar in der Szenario, in dem Sie nur nach dem Standardnamen fragen müssen.

+0

sorry, die FK nicht haben sollte Eine Nicht-Null-Bedingung –

+0

auch id hinzufügen möchten, in ersten Schema, Person_has_name würde einige Einschränkung, um sicherzustellen, gibt es nur eine Standard = True pro Person_id. Aus diesem Grund und dem Grund, den du beschreibst, favorisiere ich auch Schema # 2. –

+0

jedoch hat Schema # 2 sein eigenes Problem, jetzt denke ich darüber nach. Soll default_name_id auch in der Tabelle person_has_name existieren? es ist möglich, dass es nicht geht. –

1

Wir analysieren:

  • Zweites Schema verhindern Sie mehr als eine name als Standard festlegen, aber nicht verhindern, dass Sie als Standard festlegen name einige nicht verwandten Namen.
  • Gegenüber geschieht mit dem ersten Schema.

ich Ihnen vorschlagen (zu Ihrem Zombie Benutzer) ein drittes Schema, die mathematischen Probleme löst:

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) 

); 

Grüße und traurig über Verzögerung, ich bin Verzögerung;)

0

Ich würde verwenden keiner der beiden.

Lösung 1 verhindert nicht, dass Sie 2 Standardnamen für eine Person haben.

Lösung 2 verhindert nicht, dass eine Person einen Standardnamen hat, der nicht sein ist. Sie könnten den Fremdschlüssel von default_name_id references names(id) zu (person_id, default_name_id) references person_has_name(person_id, name_id) ändern, aber dann hätten Sie Zirkelbezüge und das ist ein anderes Problem, schwer zu lösen.

Sie diese, ähnlich wie Ihre zweite Lösung verwenden:

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) 
); 

Mit dieser zusätzlichen Tabelle, für die Personen, die einen Standardnamen haben:

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

Ihre extra Tabelle ist ein 1: 1 für Leute. Was ist der Grund, diese Felder in die Extratabelle zu extrahieren? – danihp

+0

@danihp: Ja, es ist ein '1: 0..1' für Leute. Nur für diejenigen, die einen Standardnamen haben. Der Grund ist, kreisförmige Referenzen zwischen Tabellen zu eliminieren. –

+0

Ihre Lösung ist in Ordnung, wenn Sie entweder: default_name_id als Nullable setzen oder: sich mit dem Chichen-and-Egg-Problem befassen, wenn Sie in die Tabellen 'people' und' people_has_name' einfügen/löschen möchten. –

Verwandte Themen