Constraints brüchig bei Vererbung?

Hallo,

allem Anschein nach wirken sich nachträglich (in Elterntabellen) eingefügte Constraints nicht auf die Kinder aus- das macht sie bei Vererbung praktisch wertlos :frowning:

Ein Beispiel:


– Eltern-Tabelle
create table tiere (rasse varchar(30));

– ein Kind
create table milchvieh (milchmenge real) inherits (tiere);

insert into milchvieh (rasse, milchmenge) values (‘Ziege’, 12.1);


– neue Regel: jedes Tier braucht einen Namen:
alter table tiere add constraint primary key (rasse);

– wirkt sich nicht auf milchvieh aus!
insert into milchvieh (milchmenge) values (7.0);
insert into milchvieh (rasse, milchmenge) values (‘Kroete’, 0.01);


pg=# select coalesce (rasse, ‘ICH BIN EIN BUG’) Rasse from tiere;
rasse

Ziege
ICH BIN EIN BUG
Kroete
(3 Zeilen)


– Test: Aenderung der Spalte der Eltern-Tabelle:
alter table tiere alter column rasse type varchar(31);


pg=# \d tiere;
Tabelle »public.tiere«
Spalte | Typ | Attribute
--------±----------------------±----------
rasse | character varying(31) | not null
Indexe:
“tiere_pkey” PRIMARY KEY, btree (rasse)


pg=# \d milchvieh;
Tabelle »public.milchvieh«
Spalte | Typ | Attribute
------------±----------------------±----------
rasse | character varying(31) |
milchmenge | real |
Erbt von: tiere


pg=# select version();
version

PostgreSQL 8.4.2, compiled by Visual C++ build 1400, 32-bit
(1 Zeile)


Ist das ein bekanntes Verhalten?

Ja. Und es ist sogar noch viel schlimmer:

test=# create table tiere (rasse varchar(30) primary key);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tiere_pkey" for table "tiere"
CREATE TABLE
test=*# create table milchvieh (milchmenge real) inherits (tiere);
CREATE TABLE
test=*# \d tiere
            Table "public.tiere"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 rasse  | character varying(30) | not null
Indexes:
    "tiere_pkey" PRIMARY KEY, btree (rasse)

test=*# \d milchvieh
            Table "public.milchvieh"
   Column   |         Type          | Modifiers
------------+-----------------------+-----------
 rasse      | character varying(30) | not null
 milchmenge | real                  |
Inherits: tiere

test=*#

Siehst Du auch das, was ich sehen? Der PK ist nicht vererbt!!1elf.

Die gute Nachricht: dies ist so auch dokumentiert:

All check constraints and not-null constraints on a parent table are automatically inherited by its children. Other types of constraints (unique, primary key, and foreign key constraints) are not inherited.

Aus: PostgreSQL: Documentation: Manuals: PostgreSQL 8.4: Inheritance

Hättest Du nachträglich NOT NULL für die Spalte definiert, so wäre dies ‘durchgeschlagen’:

test=# \h alter table
test=# create table tiere (rasse varchar(30));
CREATE TABLE
test=*# create table milchvieh (milchmenge real) inherits (tiere);
CREATE TABLE
test=*# alter table tiere alter column rasse set not null;
ALTER TABLE
test=*# \d tiere
            Table "public.tiere"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 rasse  | character varying(30) | not null

test=*# \d milchvieh
            Table "public.milchvieh"
   Column   |         Type          | Modifiers
------------+-----------------------+-----------
 rasse      | character varying(30) | not null
 milchmenge | real                  |
Inherits: tiere
[/quote]

Du wirst Dich fragen, warum dies so ist: ein PK z.B. erfordert einen zusätzlichen Index, der angelegt werden müßte. Ein NOT NULL nicht. Ich vermute mal, daß daher ein PK nicht vererbt wird. Das ist auch etwas, bei bei table-partitioning zu beachten ist.


Andreas

Nicht nur das: Ich sehe, dass bei dir die Milchvieh-Tabelle mit NOT NULL Constraint auf ‘rasse’ gelistet wird. Das heisst also, dass es nicht ausreicht die Attribute der Eltern-Tabelle anzusehen, sondern ich muss tatsaechlich auf die Indizes schauen um besser raten zu koennen, ob das constaint vererbt wird.
[INDENT](Nutzt natuerlich auch nichts; meine animals Tabelle hatte ich gleich mit not null definiert, und nachtraeglich einen PK verpasst- sodass sie genau so aussah wie Tiere – und mich wirklich gewundert, warum animals constraints vererbt, Tiere aber nicht.)
[/INDENT]Schade, dass Postgresql an dieser Stelle so kaputt ist (mysql’ish geradezu): klar liegt auf dieser Spalte ein constraint, aber wegen … interessiert mich das jetzt gerade nicht.

Danke fuer die Erklaerung.

Immerhin sind ab 8.5 Kinder gleichberechtigt (und werden von \d gelistet.)

Ich sehe nicht wirklich, daß da was kapott ist.

Um bei Deinem beispiel zu bleiben: In Tiere.rasse selbst kannst Du (wegens PK) nur einmal ‘Hauskatze’ eingeben, aber Du hast zu Hause 2 solche Viecher, die Du in einer vererbten Kindtabelle “Meine Haustiere” unter dieser Rasse abspeichern kannst. Eine Vererbung des Unique Constraints von tiere.rasse auf Deine Haustiertabelle wäre hier also völlig fehl am Platz.

Also, nicht alles, was nicht gleich wie erwartet funktioniert, muß ein Fehler sein. Die Art und Weise, wie PG Vererbung implementiert, ist klar dokumentiert. Wie schon gesagt: ich sehe weder Fehler noch Problem.


Andreas

Ich finde, dass

pg=# select count (*) from tiere where rasse is null;
 count
-------
     2
(1 Zeile)

und

pg=# \d tiere;
           Tabelle »public.tiere«
 Spalte |          Typ          | Attribute
--------+-----------------------+-----------
 rasse  | character varying(31) | not null
Indexe:
    "tiere_pkey" PRIMARY KEY, btree (rasse)

sich ausschliessen.
Wenn ein RDBMS ein Constraint nicht durchsetzt, ist es imho kaputt & das laesst sich schwerlich wegdiskutieren.

Kritisch sind meiner Meinung nach weiterhin

  • der fehlende Hinweis, dass (der Kinder wegen) das Constraint u.U. nicht durchgesetzt werden kann. Von einem System, dass bei einem bei jedem PK oder unique erzaehlt, dass es dazu einen passenden Index anlegt, kann man das erwarten.
  • dass (bis einschliesslich 8.4) in der description die Kinder nicht erwaehnt werden.

Anyway, ich werde lernen damit zu leben.
Im Augenblick verbuche ich Vererbung genauso wie Arrays als theoretisch ganz nett.

Ja, so ganz logisch ist das nicht alles. Ich hab das auch grad eben mal in einer Mailinglist nachgefragt. PG sieht einen Unterschied zwischen einem ‘not null’ und einen ‘primary key’, der ja auch ein ‘not null’ mit bewirkt. Zumindest dann, wenn man dies, also den pk oder das not null, später erzeugt.


Andreas

Just for info: Re: possible bug with inheritance?

Andreas