Thread: Foreign keys and inheritance
I thought I had understood the question of primary key and foreign keys in the context of inheritance, but it seems I don't, and I would appreciate some light over this situation. Here's the setup:
I have a parent table entitled "generic", composed of a SERIAL primary key "id" plus a few other columns, one of which is a not-null character-type entitled "kind". The possible values of "kind" are constrained to be only 'a' or 'b'.
Table "generic" has two children: "child_a" and "child_b". In "child_a", the column "kind" is constrained to be 'a'; in "child_b", the value of "kind" is constrained to 'b'. The two children differ slightly in the structure of the columns that aren't part of their "generic" parent. Moreover, all the tuples of "generic" have to belong to either "child_a" or "child_b". (In other words, any tuple appearing in "generic" has been inserted in either "child_a" or "child_b".)
In parallel with all that, I have another table "family" containing an attribute which references (as foreign key) the "id" of table "generic". You see, "family" isn't really bothered to know whether it is referencing a tuple in "child_a" or one in "child_b": if we need to access the extra columns proper to the children, we'll do that at a later stage...
However, Postgres isn't too happy about that: when, in cousin, I insert a reference to a tuple of "generic", I am told:
ERROR: insert or update on table "cousin" violates foreign key constraint "cousin_generic_fkey"
DETAILS: Key (family_relative)=(5) is not present in table "generic"
All the while, a SELECT on "generic" will give something like:
id | kind | reliability
----+------+-------------
4 | b | 2
5 | a | 8
In other words, although the tuple with id=5 appears in the SELECT query, it seems that Postgres would rather I referenced it inside "child_a" rather than inside "generic". All along, I had been under the impression that a tuple belonging to a child automatically belongs to the parent, yet I wouldn't be able to reference that tuple???
Is that normal behaviour? Can I relax the foreign key constraint so as to be able to reference any item within "generic", whether the tuple originally came from "generic" or from one of its children?
(Running PostgreSQL v.8.1.3 on WindowsXP.)
I have a parent table entitled "generic", composed of a SERIAL primary key "id" plus a few other columns, one of which is a not-null character-type entitled "kind". The possible values of "kind" are constrained to be only 'a' or 'b'.
Table "generic" has two children: "child_a" and "child_b". In "child_a", the column "kind" is constrained to be 'a'; in "child_b", the value of "kind" is constrained to 'b'. The two children differ slightly in the structure of the columns that aren't part of their "generic" parent. Moreover, all the tuples of "generic" have to belong to either "child_a" or "child_b". (In other words, any tuple appearing in "generic" has been inserted in either "child_a" or "child_b".)
In parallel with all that, I have another table "family" containing an attribute which references (as foreign key) the "id" of table "generic". You see, "family" isn't really bothered to know whether it is referencing a tuple in "child_a" or one in "child_b": if we need to access the extra columns proper to the children, we'll do that at a later stage...
However, Postgres isn't too happy about that: when, in cousin, I insert a reference to a tuple of "generic", I am told:
ERROR: insert or update on table "cousin" violates foreign key constraint "cousin_generic_fkey"
DETAILS: Key (family_relative)=(5) is not present in table "generic"
All the while, a SELECT on "generic" will give something like:
id | kind | reliability
----+------+-------------
4 | b | 2
5 | a | 8
In other words, although the tuple with id=5 appears in the SELECT query, it seems that Postgres would rather I referenced it inside "child_a" rather than inside "generic". All along, I had been under the impression that a tuple belonging to a child automatically belongs to the parent, yet I wouldn't be able to reference that tuple???
Is that normal behaviour? Can I relax the foreign key constraint so as to be able to reference any item within "generic", whether the tuple originally came from "generic" or from one of its children?
(Running PostgreSQL v.8.1.3 on WindowsXP.)
All along, I had been under the impression that a > tuple belonging to a child automatically belongs to the parent, yet I > wouldn't be able to reference that tuple??? I was under the same impression also. However, I didn't take any time to play with inherited tables as I wanted to relate two child tables together via a relate table. The docs explicitly same that currently this isn't possible. (However, it is on the to-do list for 8.2 :-D. I am really excited about that. It should be added as long as it doesn't get pushed aside for more important additions.) However, if I interpret the docs correctly, could make sense that relation breaks down because the tuple only appears to be in the parent table when you select * from parent;. Notice the use of the Key work ONLY in the snippet of the 8.1.3 postgres document: In PostgreSQL, a table can inherit from zero or more other tables, and a query can reference either all rows of a table or all rows of a table plus all of its descendant tables. The latter behavior is the default. For example, the following query finds the names of all cities, including state capitals, that are located at an altitude over 500ft: SELECT name, altitude FROM cities WHERE altitude > 500; Given the sample data from the PostgreSQL tutorial (see Section 2.1), this returns: name | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953 Madison | 845 On the other hand, the following query finds all the cities that are not state capitals and are situated at an altitude over 500ft: SELECT name, altitude FROM ONLY cities WHERE altitude > 500; name | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953 Here the ONLY keyword indicates that the query should apply only to cities, and not any tables below cities in the inheritance hierarchy. Many of the commands that we have already discussed SELECT, UPDATE and DELETE support the ONLY keyword. If I was to take a guess why the relation breaks, It would be that the table inheritance really only works like a union query on two tables. So in reality, the parent table may not really have the child's tuple in it. > > Is that normal behaviour? Can I relax the foreign key constraint so as to > be able to reference any item within "generic", whether the tuple originally > came from "generic" or from one of its children? > > (Running PostgreSQL v.8.1.3 on WindowsXP.) > I was able to emulate inherited tables using one parent table and two child tables. The child table linked to the parent table with unique foriforeigns. To simplify the insertion and selection of the two child and parent tables it made use of two insert-able, update-able, delete-able views. This gives me full control and allows me to create relations on any of the tables. The down side is that this schema is labor intensive. Regards, Richard Broersma
On Apr 7, 2006, at 14:37 , Richard Broersma Jr wrote: > I was under the same impression also. However, I didn't take any > time to play with inherited > tables as I wanted to relate two child tables together via a relate > table. The docs explicitly > same that currently this isn't possible. (However, it is on the to- > do list for 8.2 :-D. Not to dampen your excitement, but the todo list at http://www.postgresql.org/docs/faqs.TODO.html is for *all* todos, those being implemented for 8.2 and those that people have thought might be nice but haven't done any work on. Unless something's already been committed to head, or you see something on the patch list (or are submitting a patch yourself? :) ), there's no guarantee that anything on the todo list will be in 8.2. (Or did I miss something? I've been known to.) Patches welcome :) Michael Glaesemann grzm myrealbox com