Datenbank Modellierung

Hallo Forum,

Ich habe mal wieder eine Frage und hoffe dass jemand mir bei der Lösung auf die Sprünge helfen kann.

Es geht um die Speicherung von Pflanzen mit Familie,Gattung,Art Sorte in einer Datenbank.

Hierbei ist es jetzt so, dass jede Pflanze eine Familie und eine Gattung haben muss. Ausserdem hat dann jede Pflanze eine Art oder eine Sorte oder eine Art und Sorte. D.h. Familie und Gattung gibt es immer. Art kann auch leer sein, wenn eine Sorte gesetzt ist, Art kann auch leer sein wenn eine Sorte gesetzt ist.

Als quasi folgende Kombinationen sind möglich.
familie | gattung | art | sorte
familie | gattung | “leer” | sorte
familie | gattung | art | “leer”

Jede Familie kann beliebig viele Gattungen haben, aber jede Gattung hat nur eine Familie (1:n)
Jede Gattung kann beliebig viele Arten haben, und jede Art kann zu beliebig vielen Gattungen gehören (n:m)
Jede Art kann beliebig viele Sorten haben, und jede Sorte kann zu beliebig vielen Arten gehören (n:m)
Jede Gattung kann beliebig viele Sorten haben, und jede Sorte kann zu beliebig vielen Gattungen gehören (n:m) (Art leer)

Hiervon abhängig ist jetzt wieder die eigentlich Pflanze (Akzession). Die Pflanze wäre dann im prinzip die Pflanze im Topf. Die Akzession bezieht sich dann immer auf eine der oben genannten Kombinationen. Akzessionen können auch “doppelt” vorkommen (wenn man quasi 2x diesselbe Pflanze einkauft beziehen die beiden akzessionen sich auf dieselbe Kombination).

Das Problem was ich jetzt habe ist, wie ich die Akzession an die entsprechende Kombination bekomme oder wie kann ich das sinnvoll speichern, damit das alle Fälle abdeckt? Ausserdem weiss ich nicht genau wie ich damit umgehen soll, dass ja nicht alle Attribute belegt sein müssen (Art oder Sorte können ja auch leer sein). Es gibt ja quasi 3 verschiedene Möglichkeiten und je nachdem müsste ich ja dann drei verschiedene Tabellen anzapfen. oder steh ich da jetzt völlig auf dem Schlauch?

Ich hoffe jemand kommt jetzt raus?

Für eure Hilfe bedanke ich mich recht herzlich im Voraus.

Lieber Gruss
Hanno

test=# create table art(id int primary key);
CREATE TABLE
test=*# create table sorte(id int primary key);
CREATE TABLE
test=*# create table pflanze (art int references art, sorte int references sorte, check(coalesce(art,0)+coalesce(sorte,0) > 0));
CREATE TABLE
test=*# insert into art values (1);
INSERT 0 1
test=*# insert into sorte values (1);
INSERT 0 1
test=*# insert into pflanze values (1,1);
INSERT 0 1
test=*# insert into pflanze values (1,null);
INSERT 0 1
test=*# insert into pflanze values (null,1);
INSERT 0 1
test=*# insert into pflanze values (null,null);
ERROR:  new row for relation "pflanze" violates check constraint "pflanze_check"
DETAIL:  Failing row contains (null, null).
STATEMENT:  insert into pflanze values (null,null);
ERROR:  new row for relation "pflanze" violates check constraint "pflanze_check"
DETAIL:  Failing row contains (null, null).

Damit erzwingst Du, daß mind. eines der Felder gesetzt ist, das war doch jetzt Dein Problem, oder?

Hallo nochmal,
Danke für die schnelle Antwort. Das scheint gut zu funktionieren. :slight_smile:
Jetzt habe ich aber eine Anschlussfrage zu den Checks.
Ich habe jetzt eine Tabelle mit den Gattungen,Arten,SOrten
id | id_sorte | id_art | id_gattung

Wobei wie gesagt id_sorte oder id_art leer sein kann. Wie kann ich jetzt sicherstellen, dass ich keine doppelten Werte eingebe. Also die Kombination sorte,art,gattung nur einmal vorkommt? Ich habe es mit einem unique constraint versucht, aber irgendwie scheint das nicht zu gehen. Kann das an den NULL-Werten liegen? Wenn alle Attribute gesetzt sind geht es. Aber immer wenn sorte oder art NULL sind funktioniert der constarint nicht. Wie muss ich den constraint anlegen, damit das geht?

CONSTRAINT uq_sorte_art_gattung
UNIQUE (id_sorte, id_art, id_gattung)

Kann mir hier eventuell noch jemand auf die Sprünge helfen, bitte?

Für Hilfe bedanke ich mich wie immer recht herzlich im Voraus.

Gruss
Hanno

Auch so:

test=*# create unique index idx_pflanze on pflanze(coalesce(art,0), coalesce(sorte,0));
CREATE INDEX
test=*# insert into pflanze values (null,1);
INSERT 0 1
test=*# insert into pflanze values (null,1);
ERROR:  duplicate key value violates unique constraint "idx_pflanze"
DETAIL:  Key ((COALESCE(art, 0)), (COALESCE(sorte, 0)))=(0, 1) already exists.
STATEMENT:  insert into pflanze values (null,1);
ERROR:  duplicate key value violates unique constraint "idx_pflanze"
DETAIL:  Key ((COALESCE(art, 0)), (COALESCE(sorte, 0)))=(0, 1) already exists.

verwende für den coalsce - Wert etwas, was sonst nie vorkommen kann, also hier z.B. 0, wenn es keine Art order Sorte mit id=0 geben kann.

super,
Das scheint zu funktionieren. Vielen, vielen Dank