Re: Using a serial primary key as a foreign key in a second table - Mailing list pgsql-novice

From Sean Davis
Subject Re: Using a serial primary key as a foreign key in a second table
Date
Msg-id 200612210838.21321.sdavis2@mail.nih.gov
Whole thread Raw
In response to Re: Using a serial primary key as a foreign key in a second table  (Nathaniel <naptrel@yahoo.co.uk>)
Responses Re: Using a serial primary key as a foreign key in a second table
List pgsql-novice
On Thursday 21 December 2006 08:04, Nathaniel wrote:
> > You simply add the company to the database, get its ID, and then
> > insert the
> > person with the appropriate company_id.  That is the simplest way
> > to think
> > about the process.  This will work for as many concurrent users as
> > you like.
>
> The problem here is that the company_id is the only field that is
> guaranteed to uniquely identify a company record: it's possible
> (albeit unlikely) that there is another "Looney Tunes" in the company
> table, but that one is the lesser-known Canadian company that
> manufactures bird whistles, and Bugs Bunny doesn't work for them. As
> a dumb human I can tell the difference (perhaps by looking at the
> company address field) but my clever computer is more persnickety. So
> I don't know how to identify the relevant record from which to "get
> its ID" without knowing its ID!
>
> Searching the internet, I found these two examples from an Oracle-
> related site and am looking to implement something analagous that
> works in postgres, but I'm new to PL/pgSQL and commands like
> "nextval" so am struggling.
>
>
> DECLARE
>    l_company_id  companies.company_id%TYPE;
> BEGIN
>    -- Select the next sequence value.
>    SELECT companies_seq.NEXTVAL
>    INTO   l_company_id
>    FROM   dual;
>
>    -- Use the value to populate the master table.
>    INSERT INTO companies (company_id, company_name)
>    VALUES (l_company_id, 'Looney Tunes');
>
>    -- Reuse the value to populate the FK link in the detail table.
>    INSERT INTO people (company_id, person_name)
>    VALUES (l_company_id, 'Bug Bunny');
>
>    COMMIT;
> END;
>
>
> DECLARE
>    l_company_id  companies.company_id%TYPE;
> BEGIN
>    -- Populate the master table, returning the sequence value.
>    INSERT INTO companies (company_id, company_name)
>    VALUES (companies_seq.NEXTVAL, 'Looney Tunes')
>    RETURNING company_id INTO l_company_id;
>
>    -- Use the returned value to populate the FK link in the detail
> table.
>    INSERT INTO people (company_id, person_name)
>    VALUES (l_company_id, 'Bugs Bunny');
>
>    COMMIT;
> END;
>
> Can anyone tell me how to translate either (I prefer the latter) into
> postgres-compliant SQL?

See here:

http://www.postgresql.org/docs/current/static/sql-insert.html

You can use this returned ID in your next insert.  Alternatively, you can
select from the associated company sequence to get the "next" value for use
in both insert statements (company and then person).

The beginning of your email represents a larger problem, though.  Even though
you have chosen an autoincrementing integer as your primary key, that doesn't
guarantee uniqueness.  In fact, if you use your method of inserting a company
and a person in the say shown in the above examply, you will end up with
exactly as many company entries as person entries.  So, what you really want
to do is to specify what makes a company unique (using a unique key
constraint) so that you can look up a company by that unique key (can be
combination of city, state, and name, for example).  IF and only if the
company does not exist in your database do you do your insert.  Otherwise,
you use the id from your lookup.  This is an important point in database
design.  See here:

http://en.wikipedia.org/wiki/Database_normalization

Hope that helps.

Sean

pgsql-novice by date:

Previous
From: Nathaniel
Date:
Subject: Re: Using a serial primary key as a foreign key in a second table
Next
From: Nathaniel
Date:
Subject: Re: Using a serial primary key as a foreign key in a second table