Discussion:
Getting the OID of inserted row in a rule
(too old to reply)
Bradley Kieser
2004-09-22 13:21:42 UTC
Permalink
I have a rule on a view that needs to insert into two tables. The one
table has a serial ID as its unique key. The second table links to the
first one in one of its columns.

I would prefer to keep this as a rule-based solution and not have to
write a function as I hope to relicate the solution across many views.

I need to either be able to select nextval() the ID for the first table
and somehow store this in the rule (but I don't see that rules support
variables) or I need to somehow obtain the OID from the first insert in
order to select back the ID that was assigned during the insert and pass
it to the second insert (trivial to do as the second insert is then
simply a select-based insert, provided that I know the OID of that first
row!).

Does anyone know how to do this?

Here is the problem graphically:

Table A:
id serial
xxx text
[etc]


Table B:
col1,
col2,
col3 foreign key to id in table A

I need to insert a new record into both the above where b.col3
references a.id

Thanks,

Brad

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to ***@postgresql.org)
Michael Fuhr
2004-09-22 15:26:43 UTC
Permalink
Post by Bradley Kieser
I have a rule on a view that needs to insert into two tables. The one
table has a serial ID as its unique key. The second table links to the
first one in one of its columns.
I would prefer to keep this as a rule-based solution and not have to
write a function as I hope to relicate the solution across many views.
I need to either be able to select nextval() the ID for the first table
and somehow store this in the rule (but I don't see that rules support
variables) or I need to somehow obtain the OID from the first insert in
order to select back the ID that was assigned during the insert and pass
it to the second insert (trivial to do as the second insert is then
simply a select-based insert, provided that I know the OID of that first
row!).
The second insert should be able to use currval() to get the current
value of the sequence used in the first insert. Here's an example:

CREATE RULE v_ins AS ON INSERT TO v DO INSTEAD (
INSERT INTO a (xxx) VALUES (NEW.xxx);
INSERT INTO b (col1, col2, col3) VALUES (NEW.col1, NEW.col2, currval('a_id_seq'))
);
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faqs/FAQ.html
Bradley Kieser
2004-09-22 15:30:06 UTC
Permalink
Hi Michael,

But what if another insert happens in the mean time? Then the sequence
would have advanced that the data will be scrambled. |Given that this
could be a very active dataset, that situation is almost certain to occur.

Brad
Post by Michael Fuhr
Post by Bradley Kieser
I have a rule on a view that needs to insert into two tables. The one
table has a serial ID as its unique key. The second table links to the
first one in one of its columns.
I would prefer to keep this as a rule-based solution and not have to
write a function as I hope to relicate the solution across many views.
I need to either be able to select nextval() the ID for the first table
and somehow store this in the rule (but I don't see that rules support
variables) or I need to somehow obtain the OID from the first insert in
order to select back the ID that was assigned during the insert and pass
it to the second insert (trivial to do as the second insert is then
simply a select-based insert, provided that I know the OID of that first
row!).
The second insert should be able to use currval() to get the current
CREATE RULE v_ins AS ON INSERT TO v DO INSTEAD (
INSERT INTO a (xxx) VALUES (NEW.xxx);
INSERT INTO b (col1, col2, col3) VALUES (NEW.col1, NEW.col2, currval('a_id_seq'))
);
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org
Michael Fuhr
2004-09-22 15:59:22 UTC
Permalink
Post by Bradley Kieser
Post by Michael Fuhr
CREATE RULE v_ins AS ON INSERT TO v DO INSTEAD (
INSERT INTO a (xxx) VALUES (NEW.xxx);
INSERT INTO b (col1, col2, col3) VALUES (NEW.col1, NEW.col2,
currval('a_id_seq'))
);
But what if another insert happens in the mean time? Then the sequence
would have advanced that the data will be scrambled. |Given that this
could be a very active dataset, that situation is almost certain to occur.
currval() returns the last value returned by nextval() in *this session*.

http://www.postgresql.org/docs/7.4/static/functions-sequence.html
http://www.postgresql.org/docs/faqs/FAQ.html#4.15.3

Do you have multiple processes or threads sharing the same connection?
Perhaps one of the developers can comment on the possibility of a race
condition in that case.
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend
Bradley Kieser
2004-09-22 16:15:40 UTC
Permalink
Ah!
I didn't know that!
Michael, thank you so much! No, I don't have anything sharing these
sessions, they are rules in the back end so they should (unless someone
tells me differently) AFAIK be in their own threads.

Top man!

Brad
Post by Michael Fuhr
Post by Bradley Kieser
Post by Michael Fuhr
CREATE RULE v_ins AS ON INSERT TO v DO INSTEAD (
INSERT INTO a (xxx) VALUES (NEW.xxx);
INSERT INTO b (col1, col2, col3) VALUES (NEW.col1, NEW.col2,
currval('a_id_seq'))
);
But what if another insert happens in the mean time? Then the sequence
would have advanced that the data will be scrambled. |Given that this
could be a very active dataset, that situation is almost certain to occur.
currval() returns the last value returned by nextval() in *this session*.
http://www.postgresql.org/docs/7.4/static/functions-sequence.html
http://www.postgresql.org/docs/faqs/FAQ.html#4.15.3
Do you have multiple processes or threads sharing the same connection?
Perhaps one of the developers can comment on the possibility of a race
condition in that case.
---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to ***@postgresql.org so that your
message can get through to the mailing list cleanly

Gaetano Mendola
2004-09-22 16:11:38 UTC
Permalink
Post by Bradley Kieser
Hi Michael,
But what if another insert happens in the mean time? Then the sequence
would have advanced that the data will be scrambled. |Given that this
could be a very active dataset, that situation is almost certain to occur.
I think you are wrong, the sequence are not affected by transactions ( on rollback
the serial is not rolledback ), but however the value are isolated between transactions.

I don't see the problem:

#section1

begin;
insert into test (b) values ( 1 );

#section2

begin;
insert into test (b) values ( 1 );


#section1

select currval('test_a_seq'); <==== give 1


#section2


select currval('test_a_seq'); <==== give 2




Regards
Gaetano Mendola
Loading...