1
1
<!--
2
- $PostgreSQL: pgsql/doc/src/sgml/advanced.sgml,v 1.43 2004/08/07 19:53:48 tgl Exp $
2
+ $PostgreSQL: pgsql/doc/src/sgml/advanced.sgml,v 1.44 2004/08/08 01:51:05 momjian Exp $
3
3
-->
4
4
5
5
<chapter id="tutorial-advanced">
@@ -108,7 +108,7 @@ CREATE TABLE cities (
108
108
);
109
109
110
110
CREATE TABLE weather (
111
- city varchar(80) references cities,
111
+ city varchar(80) references cities(city) ,
112
112
temp_lo int,
113
113
temp_hi int,
114
114
prcp real,
@@ -327,16 +327,97 @@ COMMIT;
327
327
</indexterm>
328
328
329
329
<para>
330
- Inheritance is a concept from object-oriented databases. It opens
331
- up interesting new possibilities of database design.
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.
336
+ </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>
391
+
392
+ </para>
393
+ <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>
332
412
</para>
333
413
334
414
<para>
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:
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:
340
421
341
422
<programlisting>
342
423
CREATE TABLE capitals (
@@ -359,7 +440,7 @@ CREATE VIEW cities AS
359
440
</programlisting>
360
441
361
442
This works OK as far as querying goes, but it gets ugly when you
362
- need to update several rows, to name one thing.
443
+ need to update several rows, for one thing.
363
444
</para>
364
445
365
446
<para>
0 commit comments