Обсуждение: Getting the OID of inserted row in a rule
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
On Wed, Sep 22, 2004 at 02:21:42PM +0100, Bradley Kieser wrote: > 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/
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 Michael Fuhr wrote: >On Wed, Sep 22, 2004 at 02:21:42PM +0100, Bradley Kieser wrote: > > >>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')) >); > > >
On Wed, Sep 22, 2004 at 04:30:06PM +0100, Bradley Kieser wrote: > Michael Fuhr wrote: > > >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/
Bradley Kieser wrote: > 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
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 Michael Fuhr wrote: >On Wed, Sep 22, 2004 at 04:30:06PM +0100, Bradley Kieser wrote: > > >>Michael Fuhr wrote: >> >> >> >>>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. > > >