Skip to content

Commit 35a5fb6

Browse files
committed
Move expanded discussion of inheritance's limitations out of tutorial
and into ddl.sgml. Rewrite for more completeness and (hopefully) clarity.
1 parent 33bf242 commit 35a5fb6

File tree

3 files changed

+110
-146
lines changed

3 files changed

+110
-146
lines changed

doc/src/sgml/advanced.sgml

Lines changed: 23 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/advanced.sgml,v 1.44 2004/08/08 01:51:05 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/advanced.sgml,v 1.45 2004/08/08 21:33:11 tgl Exp $
33
-->
44

55
<chapter id="tutorial-advanced">
@@ -103,16 +103,16 @@ SELECT * FROM myview;
103103

104104
<programlisting>
105105
CREATE TABLE cities (
106-
city varchar(80) primary key,
107-
location point
106+
city varchar(80) primary key,
107+
location point
108108
);
109109

110110
CREATE TABLE weather (
111-
city varchar(80) references cities(city),
112-
temp_lo int,
113-
temp_hi int,
114-
prcp real,
115-
date date
111+
city varchar(80) references cities(city),
112+
temp_lo int,
113+
temp_hi int,
114+
prcp real,
115+
date date
116116
);
117117
</programlisting>
118118

@@ -327,97 +327,16 @@ COMMIT;
327327
</indexterm>
328328

329329
<para>
330-
Inheritance is a concept from object-oriented databases. Although
331-
it opens up interesting new possibilities of database design,
332-
this feature is currently unmaintained and known to have serious
333-
gotchas in its foreign key implementation, which you should take
334-
care to avoid. The fixes below are probably version-specific and may
335-
require updates in the future.
330+
Inheritance is a concept from object-oriented databases. It opens
331+
up interesting new possibilities of database design.
336332
</para>
337-
<para>
338-
The example below illustrates the gotcha.
339-
</para>
340-
<para>
341-
<programlisting>
342-
BEGIN;
343-
CREATE TABLE foo (
344-
foo_id SERIAL PRIMARY KEY
345-
);
346-
347-
CREATE TABLE parent (
348-
parent_id SERIAL PRIMARY KEY
349-
, foo_id INTEGER NOT NULL REFERENCES foo(foo_id) ON DELETE CASCADE
350-
, parent_1_text TEXT NOT NULL
351-
);
352-
353-
CREATE TABLE child_1 (
354-
child_1_text TEXT NOT NULL
355-
) INHERITS(parent);
356-
357-
CREATE TABLE child_2 (
358-
child_2_text TEXT NOT NULL
359-
) INHERITS(parent);
360-
361-
INSERT INTO foo VALUES(DEFAULT);
362-
INSERT INTO child_1 (foo_id, parent_1_text, child_1_text)
363-
VALUES (currval('public.foo_foo_id_seq'), 'parent text 1', 'child_1 text 1');
364-
365-
INSERT INTO foo VALUES(DEFAULT);
366-
INSERT INTO child_1 (foo_id, parent_1_text, child_1_text)
367-
VALUES (currval('public.foo_foo_id_seq'), 'parent text 2', 'child_1 text 2');
368-
369-
INSERT INTO foo VALUES(DEFAULT);
370-
INSERT INTO child_2 (foo_id, parent_1_text, child_2_text)
371-
VALUES (currval('foo_foo_id_seq'), 'parent text 3', 'child_2 text 1');
372-
373-
DELETE FROM foo WHERE foo_id = 1;
374-
375-
SELECT * FROM parent;
376-
parent_id | foo_id | parent_1_text
377-
-----------+--------+---------------
378-
1 | 1 | parent text 1
379-
2 | 2 | parent text 2
380-
3 | 3 | parent text 3
381-
(3 rows)
382-
383-
SELECT * FROM child_1;
384-
parent_id | foo_id | parent_1_text | child_1_text
385-
-----------+--------+---------------+----------------
386-
1 | 1 | parent text 1 | child_1 text 1
387-
2 | 2 | parent text 2 | child_1 text 2
388-
(2 rows)
389-
ROLLBACK;
390-
</programlisting>
391333

392-
</para>
393334
<para>
394-
Oops!! None of parent, child or foo should have any rows with
395-
foo_id = 1 in them. Here is a way to fix the above tables.
396-
</para>
397-
398-
<para>
399-
To fix the gotcha, you must put foreign key constraints on each of
400-
the child tables, as they will not be automatically inherited as
401-
you might expect.
402-
</para>
403-
404-
<para>
405-
<programlisting>
406-
ALTER TABLE child_1 ADD CONSTRAINT cascade_foo
407-
FOREIGN KEY (foo_id) REFERENCES foo(foo_id) ON DELETE CASCADE;
408-
409-
ALTER TABLE child_2 ADD CONSTRAINT cascade_foo
410-
FOREIGN KEY (foo_id) REFERENCES foo(foo_id) ON DELETE CASCADE;
411-
</programlisting>
412-
</para>
413-
414-
<para>
415-
That caveat out of the way, let's create two tables: A table
416-
<classname>cities</classname> and a table
417-
<classname>capitals</classname>. Naturally, capitals are also cities,
418-
so you want some way to show the capitals implicitly when you list all
419-
cities. If you're really clever you might invent some scheme like
420-
this:
335+
Let's create two tables: A table <classname>cities</classname>
336+
and a table <classname>capitals</classname>. Naturally, capitals
337+
are also cities, so you want some way to show the capitals
338+
implicitly when you list all cities. If you're really clever you
339+
might invent some scheme like this:
421340

422341
<programlisting>
423342
CREATE TABLE capitals (
@@ -525,6 +444,14 @@ SELECT name, altitude
525444
<command>DELETE</command> -- support this <literal>ONLY</literal>
526445
notation.
527446
</para>
447+
448+
<note>
449+
<para>
450+
Although inheritance is frequently useful, it has not been integrated
451+
with unique constraints or foreign keys, which limits its usefulness.
452+
See <xref linkend="ddl-inherit"> for more detail.
453+
</para>
454+
</note>
528455
</sect1>
529456

530457

doc/src/sgml/ddl.sgml

Lines changed: 76 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.29 2004/08/07 20:44:49 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.30 2004/08/08 21:33:11 tgl Exp $ -->
22

33
<chapter id="ddl">
44
<title>Data Definition</title>
@@ -996,19 +996,12 @@ CREATE TABLE capitals (
996996
) INHERITS (cities);
997997
</programlisting>
998998

999-
In this case, a row of capitals <firstterm>inherits</firstterm> all
1000-
attributes (name, population, and altitude) from its
1001-
parent, cities. The type of the attribute name is
1002-
<type>text</type>, a native <productname>PostgreSQL</productname> type
1003-
for variable length character strings. The type of the attribute
1004-
population is
1005-
<type>float</type>, a native <productname>PostgreSQL</productname> type for double precision
1006-
floating-point numbers. State capitals have an extra
1007-
attribute, state, that shows their state. In <productname>PostgreSQL</productname>,
1008-
a table can inherit from zero or more other tables,
1009-
and a query can reference either all rows of a
1010-
table or all rows of a table plus all of its
1011-
descendants.
999+
In this case, a row of capitals <firstterm>inherits</firstterm> all
1000+
attributes (name, population, and altitude) from its parent, cities. State
1001+
capitals have an extra attribute, state, that shows their state. In
1002+
<productname>PostgreSQL</productname>, a table can inherit from zero or
1003+
more other tables, and a query can reference either all rows of a table or
1004+
all rows of a table plus all of its descendants.
10121005

10131006
<note>
10141007
<para>
@@ -1065,6 +1058,32 @@ SELECT name, altitude
10651058
support this <quote>ONLY</quote> notation.
10661059
</para>
10671060

1061+
<note>
1062+
<title>Deprecated</title>
1063+
<para>
1064+
In previous versions of <productname>PostgreSQL</productname>, the
1065+
default behavior was not to include child tables in queries. This was
1066+
found to be error prone and is also in violation of the SQL99
1067+
standard. Under the old syntax, to get the sub-tables you append
1068+
<literal>*</literal> to the table name.
1069+
For example
1070+
<programlisting>
1071+
SELECT * from cities*;
1072+
</programlisting>
1073+
You can still explicitly specify scanning child tables by appending
1074+
<literal>*</literal>, as well as explicitly specify not scanning child tables by
1075+
writing <quote>ONLY</quote>. But beginning in version 7.1, the default
1076+
behavior for an undecorated table name is to scan its child tables
1077+
too, whereas before the default was not to do so. To get the old
1078+
default behavior, set the configuration option
1079+
<literal>SQL_Inheritance</literal> to off, e.g.,
1080+
<programlisting>
1081+
SET SQL_Inheritance TO OFF;
1082+
</programlisting>
1083+
or add a line in your <filename>postgresql.conf</filename> file.
1084+
</para>
1085+
</note>
1086+
10681087
<para>
10691088
In some cases you may wish to know which table a particular row
10701089
originated from. There is a system column called
@@ -1109,39 +1128,51 @@ WHERE c.altitude &gt; 500 and c.tableoid = p.oid;
11091128

11101129
</para>
11111130

1112-
<note>
1113-
<title>Deprecated</title>
1114-
<para>
1115-
In previous versions of <productname>PostgreSQL</productname>, the
1116-
default behavior was not to include child tables in queries. This was
1117-
found to be error prone and is also in violation of the SQL99
1118-
standard. Under the old syntax, to get the sub-tables you append
1119-
<literal>*</literal> to the table name.
1120-
For example
1121-
<programlisting>
1122-
SELECT * from cities*;
1123-
</programlisting>
1124-
You can still explicitly specify scanning child tables by appending
1125-
<literal>*</literal>, as well as explicitly specify not scanning child tables by
1126-
writing <quote>ONLY</quote>. But beginning in version 7.1, the default
1127-
behavior for an undecorated table name is to scan its child tables
1128-
too, whereas before the default was not to do so. To get the old
1129-
default behavior, set the configuration option
1130-
<literal>SQL_Inheritance</literal> to off, e.g.,
1131-
<programlisting>
1132-
SET SQL_Inheritance TO OFF;
1133-
</programlisting>
1134-
or add a line in your <filename>postgresql.conf</filename> file.
1135-
</para>
1136-
</note>
1137-
11381131
<para>
1139-
A limitation of the inheritance feature is that indexes (including
1132+
A serious limitation of the inheritance feature is that indexes (including
11401133
unique constraints) and foreign key constraints only apply to single
1141-
tables, not to their inheritance children. Thus, in the above example,
1142-
specifying that another table's column <literal>REFERENCES cities(name)</>
1143-
would allow the other table to contain city names but not capital names.
1144-
This deficiency will probably be fixed in some future release.
1134+
tables, not to their inheritance children. This is true on both the
1135+
referencing and referenced sides of a foreign key constraint. Thus,
1136+
in the terms of the above example:
1137+
1138+
<itemizedlist>
1139+
<listitem>
1140+
<para>
1141+
If we declared <structname>cities</>.<structfield>name</> to be
1142+
<literal>UNIQUE</> or a <literal>PRIMARY KEY</>, this would not stop the
1143+
<structname>capitals</> table from having rows with names duplicating
1144+
rows in <structname>cities</>. And those duplicate rows would by
1145+
default show up in SELECTs from <structname>cities</>. In fact, by
1146+
default <structname>capitals</> would have no unique constraint at all,
1147+
and so could contain multiple rows with the same name.
1148+
You could add a unique constraint to <structname>capitals</>, but this
1149+
would not prevent duplication compared to <structname>cities</>.
1150+
</para>
1151+
</listitem>
1152+
1153+
<listitem>
1154+
<para>
1155+
Similarly, if we were to specify that
1156+
<structname>cities</>.<structfield>name</> <literal>REFERENCES</> some
1157+
other table, this constraint would not automatically propagate to
1158+
<structname>capitals</>. In this case you could work around it by
1159+
manually adding the same <literal>REFERENCES</> constraint to
1160+
<structname>capitals</>.
1161+
</para>
1162+
</listitem>
1163+
1164+
<listitem>
1165+
<para>
1166+
Specifying that another table's column <literal>REFERENCES
1167+
cities(name)</> would allow the other table to contain city names, but
1168+
not capital names. There is no good workaround for this case.
1169+
</para>
1170+
</listitem>
1171+
</itemizedlist>
1172+
1173+
These deficiencies will probably be fixed in some future release,
1174+
but in the meantime considerable care is needed in deciding whether
1175+
inheritance is useful for your problem.
11451176
</para>
11461177
</sect1>
11471178

doc/src/sgml/query.sgml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/query.sgml,v 1.36 2004/08/08 01:51:05 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/query.sgml,v 1.37 2004/08/08 21:33:11 tgl Exp $
33
-->
44

55
<chapter id="tutorial-sql">
@@ -284,10 +284,16 @@ COPY weather FROM '/home/user/weather.txt';
284284
<programlisting>
285285
SELECT * FROM weather;
286286
</programlisting>
287-
(here <literal>*</literal> means <quote>all columns</quote>.
288-
Note: While <literal>SELECT *</literal> is useful for off-the-cuff
289-
queries, it is considered bad style in production code for
290-
maintenance reasons) and the output should be:
287+
(here <literal>*</literal> means <quote>all columns</quote>).
288+
<footnote>
289+
<para>
290+
While <literal>SELECT *</literal> is useful for off-the-cuff
291+
queries, it is considered bad style in production code for
292+
maintenance reasons: adding a column to the table changes the results.
293+
</para>
294+
</footnote>
295+
The output should be:
296+
291297
<screen>
292298
city | temp_lo | temp_hi | prcp | date
293299
---------------+---------+---------+------+------------

0 commit comments

Comments
 (0)