Thread: foreign keys constraints, depending on each other

foreign keys constraints, depending on each other

From
zilch@home.se
Date:
I was just creating this little database for demonstrating the use of
foreign keys constraints.

I was about the create 3 tables, namely mother, father and child. Mother has
a foreign key pointing at father ( id ), and father has a foreign key
pointing at mother ( id ). Child has one pointer to mother ( id ) and one
pointer to father ( id ). How can I prevent the error message from occurring?

Ofcourse I see the problem here... just by taking away the references
keyword from the mother table takes away the problem completely.

---

DROP SEQUENCE mother_id_seq;
DROP SEQUENCE father_id_seq;
DROP SEQUENCE child_id_seq;

DROP TABLE mother;
DROP TABLE father;
DROP TABLE child;

CREATE TABLE mother (

       id           SERIAL,
       fatherID     INT4 NOT NULL REFERENCES father ( id ) ON DELETE CASCADE,

       name         TEXT,

       UNIQUE ( fatherID )

);

CREATE TABLE father (

       id           SERIAL,
       motherID     INT4 NOT NULL REFERENCES mother ( id ) ON DELETE CASCADE,

       name         TEXT,

       UNIQUE ( motherID )

);

CREATE TABLE child (

       id          SERIAL,
       motherID    INT4 NOT NULL REFERENCES mother ( id ) ON DELETE CASCADE,
       fatherID    INT4 NOT NULL REFERENCES father ( id ) ON DELETE CASCADE,

       name        TEXT

);

---

Thanks

Daniel Akerud

Re: foreign keys constraints, depending on each other

From
Stephan Szabo
Date:
On Sun, 10 Jun 2001 zilch@home.se wrote:

>
> I was just creating this little database for demonstrating the use of
> foreign keys constraints.
>
> I was about the create 3 tables, namely mother, father and child. Mother has
> a foreign key pointing at father ( id ), and father has a foreign key
> pointing at mother ( id ). Child has one pointer to mother ( id ) and one
> pointer to father ( id ). How can I prevent the error message from occurring?

You don't put the constraint at table creation time.  The table referenced
by the references has to exist.  Use ALTER TABLE to add the constraint
after creating table father.


Re: foreign keys constraints, depending on each other

From
zilch@home.se
Date:
> > I was just creating this little database for demonstrating the use of
> > foreign keys constraints.
> >
> > I was about the create 3 tables, namely mother, father and child. Mother has
> > a foreign key pointing at father ( id ), and father has a foreign key
> > pointing at mother ( id ). Child has one pointer to mother ( id ) and one
> > pointer to father ( id ). How can I prevent the error message from occurring?
>
> You don't put the constraint at table creation time.  The table referenced
> by the references has to exist.  Use ALTER TABLE to add the constraint
> after creating table father.
>

I tried:

BEGIN;
SET CONSTRAINTS ALL DEFERRED;
INSERT INTO mother (fatherID, name) VALUES ( 1, 'mamma' ) ;
INSERT INTO father (motherID, name) VALUES ( 1, 'pappa' ) ;
INSERT INTO child (motherID, fatherID, name) VALUES (1, 1, 'barn 1') ;
INSERT INTO child (motherID, fatherID, name) VALUES (1, 1, 'barn 2') ;
COMMIT;

...which did not work. Still it complains about key referenced from mother not
found in father.

---
Daniel Akerud




Re: foreign keys constraints, depending on each other

From
Stephan Szabo
Date:
On Sun, 10 Jun 2001 zilch@home.se wrote:

>
> > > I was just creating this little database for demonstrating the use of
> > > foreign keys constraints.
> > >
> > > I was about the create 3 tables, namely mother, father and child. Mother has
> > > a foreign key pointing at father ( id ), and father has a foreign key
> > > pointing at mother ( id ). Child has one pointer to mother ( id ) and one
> > > pointer to father ( id ). How can I prevent the error message from occurring?
> >
> > You don't put the constraint at table creation time.  The table referenced
> > by the references has to exist.  Use ALTER TABLE to add the constraint
> > after creating table father.
> >
>
> I tried:
>
> BEGIN;
> SET CONSTRAINTS ALL DEFERRED;
> INSERT INTO mother (fatherID, name) VALUES ( 1, 'mamma' ) ;
> INSERT INTO father (motherID, name) VALUES ( 1, 'pappa' ) ;
> INSERT INTO child (motherID, fatherID, name) VALUES (1, 1, 'barn 1') ;
> INSERT INTO child (motherID, fatherID, name) VALUES (1, 1, 'barn 2') ;
> COMMIT;
>
> ...which did not work. Still it complains about key referenced from mother not
> found in father.

Ah, that's because you didn't define the constraints DEFERRABLE.  SET
CONSTRAINTS ALL DEFERRED only changes the state of deferrable constraints.

If you don't specify a time, it's INITIALLY IMMEDIATE.  If it's initially
immediate, it's NOT DEFERRABLE unless DEFERRABLE is explicitly given.


Re: foreign keys constraints, depending on each other

From
Marc SCHAEFER
Date:
On Sun, 10 Jun 2001 zilch@home.se wrote:

> I was about the create 3 tables, namely mother, father and child. Mother has
> a foreign key pointing at father ( id ), and father has a foreign key
> pointing at mother ( id ). Child has one pointer to mother ( id ) and one
> pointer to father ( id ). How can I prevent the error message from occurring?

Personnally, I tend to avoid those circular references in any computing
field.

I would remove the father and mother references, and add a
   is_married
relation; as a table, with a UNIQUE(father_id), UNIQUE(mother_id)
constraint (a person can be only married once).

I would keep the direct references from child.

It might a bit diminush the performance, but circular references are a
pain to handle.

Alternatively, keep only the mother -> father reference, and determine the
wife of father through query like:

   SELECT m.id FROM mother m WHERE m.father_id = ?

This can be quite efficient if the mother was looked up previously anyway.


Re: foreign keys constraints, depending on each other

From
Marc SCHAEFER
Date:
On Mon, 11 Jun 2001, Mario Weilguni wrote:

> > relation; as a table, with a UNIQUE(father_id), UNIQUE(mother_id)
> > constraint (a person can be only married once).
>
> Is not true, at least not in some arabic countries.

in that case my model is even better since it *allows* for that case (by
removing the UNIQUE constraints), where the REFERENCES model has an issue.


Re: foreign keys constraints, depending on each other

From
zilch@home.se
Date:
> > > relation; as a table, with a UNIQUE(father_id), UNIQUE(mother_id)
> > > constraint (a person can be only married once).
> >
> > Is not true, at least not in some arabic countries.
>
> in that case my model is even better since it *allows* for that case (by
> removing the UNIQUE constraints), where the REFERENCES model has an issue.

( =) )

Thanks for the tip!
I think i think i'll use that one...

Daniel Akerud


Re: foreign keys constraints, depending on each other

From
Shaun Thomas
Date:
On Sun, 10 Jun 2001 zilch@home.se wrote:

> Ofcourse I see the problem here... just by taking away the references
> keyword from the mother table takes away the problem completely.

Your problem isn't just one of references.  Your inherant table design is
flawed.  If you go by a strict relationship pairing, fatherid and motherid
should only be paired once.  You can get less tables if you use this
structure, similar to a geneology system:

---

DROP SEQUENCE seq_personid;
DROP SEQUENCE seq_relationid;

DROP TABLE person;
DROP TABLE relation;

CREATE TABLE person
(
  personid    INTEGER NOT NULL DEFAULT NEXTVAL('seq_personid'),
  first       VARCHAR(50) NOT NULL,
  middle      VARCHAR(50),
  last        VARCHAR(50) NOT NULL,
  birthdate   DATETIME NOT NULL,
  sex         CHAR(1) NOT NULL,
  CONSTRAINT  pk_person PRIMARY KEY (personid)
);

CREATE TABLE relation
(
  relationid  INTEGER NOT NULL DEFAULT NEXTVAL('seq_relationid'),
  firstid     INTEGER NOT NULL,
  secondid    INTEGER NOT NULL,
  reldate     DATETIME NOT NULL,
  reldesc     VARHCAR(50) NOT NULL,
  CONSTRAINT  pk_relation PRIMARY KEY (relationid)
);

ALTER TABLE relation ADD CONSTRAINT fk_person_personid_1 FOREIGN KEY
  (firstid) REFERENCES person (personid) ON DELETE CASCADE;
ALTER TABLE relation ADD CONSTRAINT fk_person_personid_2 FOREIGN KEY
  (secondid) REFERENCES person (personid) ON DELETE CASCADE;

CREATE SEQUENCE seq_personid
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 2147483647
  START 1
  CACHE 1;

CREATE SEQUENCE seq_relationid
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 2147483647
  START 1
  CACHE 1;

---

Theoretically, this structure lets you add and subtract parts of
your table structure at will without damaging anything.  Don't like
your constraints for a table load?  Remove them temporarily.  You
might want to also think about making another table to hold the
reldesc and key it into relation, since you most likely have a
constrained subset of defined relationships: Married, Son, Daughter,
etc.

Why not drop constraint?  Last I checked in postgres 7.0, that is
not an allowed operation.  I still suggest using this syntax though,
since the ability may be added in the future.

--
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
| Shaun M. Thomas                INN Database Programmer              |
| Phone: (309) 743-0812          Fax  : (309) 743-0830                |
| Email: sthomas@townnews.com    AIM  : trifthen                      |
| Web  : hamster.lee.net                                              |
|                                                                     |
|     "Most of our lives are about proving something, either to       |
|      ourselves or to someone else."                                 |
|                                           -- Anonymous              |
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+



Re: foreign keys constraints, depending on each other

From
Mario Weilguni
Date:
Am Montag, 11. Juni 2001 10:25 schrieb Marc SCHAEFER:
> I would remove the father and mother references, and add a
>    is_married
> relation; as a table, with a UNIQUE(father_id), UNIQUE(mother_id)
> constraint (a person can be only married once).

Is not true, at least not in some arabic countries.

--
===================================================
 Mario Weilguni                               KPNQwest Austria GmbH
 Senior Engineer Web Solutions                         Nikolaiplatz 4
 tel: +43-316-813824                                8020 graz, austria
 fax: +43-316-813824-26                    http://www.kpnqwest.at
 e-mail: mario.weilguni@kpnqwest.com
===================================================