Thread: Simple problem?

Simple problem?

From
Stan Jacobs
Date:
Hi there,

I must be confusing my syntax somehow, because I'm having trouble doing a
simple update with returned id...  As in.... I have two tables: an order
table and an orderitems table.  I need to write the order record, then use
the order_id from the order record in the insert to the orderitems record.

1. Can I use a transaction begin/end for the entire transaction if I need
to get the order_id in between the two writes?

2. How do I get the order_id from the record I just wrote?


    thanks in advance.

        -sj




Re: [GENERAL] Simple problem?

From
Peter Eisentraut
Date:
On Wed, 1 Mar 2000, Stan Jacobs wrote:

> I must be confusing my syntax somehow, because I'm having trouble doing a
> simple update with returned id...  As in.... I have two tables: an order
> table and an orderitems table.  I need to write the order record, then use
> the order_id from the order record in the insert to the orderitems record.

I assume you're using serial columns here. Table schemas always help ...

> 1. Can I use a transaction begin/end for the entire transaction if I need
> to get the order_id in between the two writes?

Sure.

> 2. How do I get the order_id from the record I just wrote?

You have to select it back out. A select on max(order_id) might do, but
you might get caught if someone else does updates on your table as well. I
am personally not so fond of serial columns because of this problem.

--
Peter Eisentraut                  Sernanders väg 10:115
peter_e@gmx.net                   75262 Uppsala
http://yi.org/peter-e/            Sweden


Re: [GENERAL] Simple problem?

From
Date:

On Thu, 2 Mar 2000, Peter Eisentraut wrote:

> On Wed, 1 Mar 2000, Stan Jacobs wrote:
>
> > 2. How do I get the order_id from the record I just wrote?
>
> You have to select it back out. A select on max(order_id) might do, but
> you might get caught if someone else does updates on your table as well. I
> am personally not so fond of serial columns because of this problem.
what? if you serial type, you can get it by curval(seqname) (see doc for
details).  Peter, how can You make such a mistake :-) no sleep for a week?


Re: [GENERAL] Simple problem?

From
"Ross J. Reedstrom"
Date:
On Thu, Mar 02, 2000 at 04:17:30PM +0100, Peter Eisentraut wrote:
> On Wed, 1 Mar 2000, Stan Jacobs wrote:
>
> > I must be confusing my syntax somehow, because I'm having trouble doing a
> > simple update with returned id...  As in.... I have two tables: an order
> > table and an orderitems table.  I need to write the order record, then use
> > the order_id from the order record in the insert to the orderitems record.
>
> I assume you're using serial columns here. Table schemas always help ...
>
> > 1. Can I use a transaction begin/end for the entire transaction if I need
> > to get the order_id in between the two writes?
>
> Sure.
>
> > 2. How do I get the order_id from the record I just wrote?
>
> You have to select it back out. A select on max(order_id) might do, but
> you might get caught if someone else does updates on your table as well. I
> am personally not so fond of serial columns because of this problem.

Peter, I was _sure_ you were around for the last few times this has come up.
PostgreSQL's 'serial' pseudo type (convenience type?) is multiuser safe.

Stan, there's a couple approaches to solving your problem:

Some (such as Tom) prefer the programmatic solution: Create a sequence
(either manually or automatically by using a 'serial' type), select
the nextval() from the sequence yourself, then insert it, rather than
depending on the default. However, it is also possible to do:

SELECT currval('table_field_seq');

Note that you're passing a string constant to the function currval,
and that constant happens to be the name of the sequence to act on. If
you sequence has MultiCaps (like if you used quoted "InitCaps" in table
or field names), you'll need the double quotes, inside the single quotes:

SELECT currval('"Table_Field_seq"');

This is multiuser safe, since currval is defined for each SQL session
(basically, from open of database to close of connection.) The only
problem with it is that currval() for a sequence is undefined in
that session until a nextval() has happened. Here's a transcript,
demonstrating the problem, as well as the multiuser safety: (NOTICEs
wrapped for readability)

test=> create table test (s serial, t text);
NOTICE:  CREATE TABLE will create implicit sequence 'test_s_seq' for
  SERIAL column 'test.s'
NOTICE:  CREATE TABLE/UNIQUE will create implicit index 'test_s_key'
  for table 'test'
CREATE
test=> select currval('test_s_seq');
ERROR:  test_s_seq.currval is not yet defined in this session
test=> insert into test (t) values ('some text');
INSERT 883807 1
test=> select currval('test_s_seq');
currval
-------
      1
(1 row)

--------- open another session in a seperate xterm -----

test=> select currval('test_s_seq');
ERROR:  test_s_seq.currval is not yet defined in this session
test=> insert into test (t) values ('some other text');
INSERT 883808 1
test=> select currval('test_s_seq');
currval
-------
      2
(1 row)

test=>

--------- back to first session -----------------------

test=> select currval('test_s_seq');
currval
-------
      1
(1 row)

test=>

Ross

--
Ross J. Reedstrom, Ph.D., <reedstrm@rice.edu>
NSBRI Research Scientist/Programmer
Computer and Information Technology Institute
Rice University, 6100 S. Main St.,  Houston, TX 77005

Re: [GENERAL] Simple problem?

From
Charles Tassell
Date:
You can do a SELECT curval('sequence_name'); to get the value you were just
assigned without worrying about other people updating, as curval gets the
current value within the current transaction (or within the current
session, either way, it works.)

Alternately, you can get the nextval before doing either of the inserts
with a select statement, and then use the returned value in you SQL.

Ex:

$OrderID=SELECT nextval('seq_order_id') AS order_id;
INSERT INTO orders (order_id, blah, blah) VALUES ($OrderID, blah, blah);
INSERT INTO items (order_id, blah, blah) VALUES ($OrderID, blah, blah);


At 11:17 AM 3/2/00, Peter Eisentraut wrote:
>On Wed, 1 Mar 2000, Stan Jacobs wrote:
>
> > I must be confusing my syntax somehow, because I'm having trouble doing a
> > simple update with returned id...  As in.... I have two tables: an order
> > table and an orderitems table.  I need to write the order record, then use
> > the order_id from the order record in the insert to the orderitems record.
>
>I assume you're using serial columns here. Table schemas always help ...
>
> > 1. Can I use a transaction begin/end for the entire transaction if I need
> > to get the order_id in between the two writes?
>
>Sure.
>
> > 2. How do I get the order_id from the record I just wrote?
>
>You have to select it back out. A select on max(order_id) might do, but
>you might get caught if someone else does updates on your table as well. I
>am personally not so fond of serial columns because of this problem.
>
>--
>Peter Eisentraut                  Sernanders väg 10:115
>peter_e@gmx.net                   75262 Uppsala
>http://yi.org/peter-e/            Sweden
>
>
>************


************


Re: [GENERAL] Simple problem?

From
Charles Tassell
Date:
You can do a SELECT curval('sequence_name'); to get the value you were just
assigned without worrying about other people updating, as curval gets the
current value within the current transaction (or within the current
session, either way, it works.)

Alternately, you can get the nextval before doing either of the inserts
with a select statement, and then use the returned value in you SQL.

Ex:

$OrderID=SELECT nextval('seq_order_id') AS order_id;
INSERT INTO orders (order_id, blah, blah) VALUES ($OrderID, blah, blah);
INSERT INTO items (order_id, blah, blah) VALUES ($OrderID, blah, blah);


At 11:17 AM 3/2/00, Peter Eisentraut wrote:
>On Wed, 1 Mar 2000, Stan Jacobs wrote:
>
> > I must be confusing my syntax somehow, because I'm having trouble doing a
> > simple update with returned id...  As in.... I have two tables: an order
> > table and an orderitems table.  I need to write the order record, then use
> > the order_id from the order record in the insert to the orderitems record.
>
>I assume you're using serial columns here. Table schemas always help ...
>
> > 1. Can I use a transaction begin/end for the entire transaction if I need
> > to get the order_id in between the two writes?
>
>Sure.
>
> > 2. How do I get the order_id from the record I just wrote?
>
>You have to select it back out. A select on max(order_id) might do, but
>you might get caught if someone else does updates on your table as well. I
>am personally not so fond of serial columns because of this problem.
>
>--
>Peter Eisentraut                  Sernanders väg 10:115
>peter_e@gmx.net                   75262 Uppsala
>http://yi.org/peter-e/            Sweden
>
>
>************


************


Re: [GENERAL] Simple problem?

From
Peter Eisentraut
Date:
On Thu, 2 Mar 2000, Ross J. Reedstrom wrote:

> Peter, I was _sure_ you were around for the last few times this has come up.
> PostgreSQL's 'serial' pseudo type (convenience type?) is multiuser safe.

I was sure of that too but I can't remember this solution. How can
sequences be "multiuser safe" if you can't roll them back?

Okay, maybe that doesn't strictly qualify, but personally, I don't like
sequences very much. But I'm sorry I misguided people. One never stops
learning ...


--
Peter Eisentraut                  Sernanders väg 10:115
peter_e@gmx.net                   75262 Uppsala
http://yi.org/peter-e/            Sweden


Re: [GENERAL] Simple problem?

From
"Steve Wolfe"
Date:
> You can do a SELECT curval('sequence_name'); to get the value you were
just
> assigned without worrying about other people updating, as curval gets the
> current value within the current transaction (or within the current
> session, either way, it works.)

  Or, my prefered method, create the table like so..

create table MyTable
(
    MyField        int4 default nextval('SomeSequence'),

...
);

  That gives you the flexibility to select the nextval of the sequence and
insert it yourself (if you need it for further processing), or to simply
let the database take care of it for itself.

steve


Re: [GENERAL] Simple problem?

From
Stan Jacobs
Date:
Thanks to everyone for their help with this-- These solutions worked
beautifully!

The only thing better than a rock-solid OpenSource database is the
support of the community behind it.... :-)  Thanks again.


"Ross J. Reedstrom" wrote:
>
> On Thu, Mar 02, 2000 at 04:17:30PM +0100, Peter Eisentraut wrote:
> > On Wed, 1 Mar 2000, Stan Jacobs wrote:
> >
> > > I must be confusing my syntax somehow, because I'm having trouble doing a
> > > simple update with returned id...  As in.... I have two tables: an order
> > > table and an orderitems table.  I need to write the order record, then use
> > > the order_id from the order record in the insert to the orderitems record.
> >
> > I assume you're using serial columns here. Table schemas always help ...
> >
> > > 1. Can I use a transaction begin/end for the entire transaction if I need
> > > to get the order_id in between the two writes?
> >
> > Sure.
> >
> > > 2. How do I get the order_id from the record I just wrote?
> >
> > You have to select it back out. A select on max(order_id) might do, but
> > you might get caught if someone else does updates on your table as well. I
> > am personally not so fond of serial columns because of this problem.
>
> Peter, I was _sure_ you were around for the last few times this has come up.
> PostgreSQL's 'serial' pseudo type (convenience type?) is multiuser safe.
>
> Stan, there's a couple approaches to solving your problem:
>
> Some (such as Tom) prefer the programmatic solution: Create a sequence
> (either manually or automatically by using a 'serial' type), select
> the nextval() from the sequence yourself, then insert it, rather than
> depending on the default. However, it is also possible to do:
>
> SELECT currval('table_field_seq');
>
> Note that you're passing a string constant to the function currval,
> and that constant happens to be the name of the sequence to act on. If
> you sequence has MultiCaps (like if you used quoted "InitCaps" in table
> or field names), you'll need the double quotes, inside the single quotes:
>
> SELECT currval('"Table_Field_seq"');
>
> This is multiuser safe, since currval is defined for each SQL session
> (basically, from open of database to close of connection.) The only
> problem with it is that currval() for a sequence is undefined in
> that session until a nextval() has happened. Here's a transcript,
> demonstrating the problem, as well as the multiuser safety: (NOTICEs
> wrapped for readability)
>
> test=> create table test (s serial, t text);
> NOTICE:  CREATE TABLE will create implicit sequence 'test_s_seq' for
>   SERIAL column 'test.s'
> NOTICE:  CREATE TABLE/UNIQUE will create implicit index 'test_s_key'
>   for table 'test'
> CREATE
> test=> select currval('test_s_seq');
> ERROR:  test_s_seq.currval is not yet defined in this session
> test=> insert into test (t) values ('some text');
> INSERT 883807 1
> test=> select currval('test_s_seq');
> currval
> -------
>       1
> (1 row)
>
> --------- open another session in a seperate xterm -----
>
> test=> select currval('test_s_seq');
> ERROR:  test_s_seq.currval is not yet defined in this session
> test=> insert into test (t) values ('some other text');
> INSERT 883808 1
> test=> select currval('test_s_seq');
> currval
> -------
>       2
> (1 row)
>
> test=>
>
> --------- back to first session -----------------------
>
> test=> select currval('test_s_seq');
> currval
> -------
>       1
> (1 row)
>
> test=>
>
> Ross
>
> --
> Ross J. Reedstrom, Ph.D., <reedstrm@rice.edu>
> NSBRI Research Scientist/Programmer
> Computer and Information Technology Institute
> Rice University, 6100 S. Main St.,  Houston, TX 77005

--



    Stan Jacobs
    Managing Director
    JTEK Interactive
    jacobs@jtek.com