Thread: INSERT RETURNING with values other than inserted ones.

INSERT RETURNING with values other than inserted ones.

From
Aleksandr Furmanov
Date:
Hello,
I want to insert new values into target table 'a' from source table 'b', and then update table 'b' with ids from table
'a',somewhat like: 

CREATE TABLE a(id SERIAL, name TEXT);
INSERT INTO a (name) VALUES('Jason');
INSERT INTO a (name) VALUES('Peter');

CREATE TABLE b(row_id serial, id INT, name TEXT);
INSERT INTO b (name) VALUES('Jason');
INSERT INTO b (name) VALUES('Peter');


WITH inserted AS (INSERT INTO a (name) SELECT b.name FROM b WHERE b.name = name RETURNING a.id)
  UPDATE b SET id = inserted.id FROM inserted WHERE inserted.row_id = b.row_id;

However this would not work for obvious reason:

WHERE inserted.row_id = b.row_id is invalid because RETURNING clause cannot return row_id.
What can be returned are only columns of 'a', but they are insufficient to identify matching records of 'b'.

So the question is - what to put in WHERE clause to match RETURNING with rows being inserted from 'b'?

Thanks!

--
Aleksandr Furmanov



Re: INSERT RETURNING with values other than inserted ones.

From
Richard Dunks
Date:
If you're just replicating the data from table A into table B, why does it need its own ID number? Wouldn't the table A
IDsuffice? 

I'd recommend using the following:

CREATE TABLE b AS ( SELECT * FROM a );

This way, you only define the columns and insert the data once, then let Postgres do the rest for you. Obviously if you
needto have a separate table B ID, you can alter as necessary.  

Good luck,
Richard Dunks

On Jun 10, 2013, at 7:29 PM, Aleksandr Furmanov <aleksandr.furmanov@gmail.com> wrote:

> Hello,
> I want to insert new values into target table 'a' from source table 'b', and then update table 'b' with ids from
table'a', somewhat like: 
>
> CREATE TABLE a(id SERIAL, name TEXT);
> INSERT INTO a (name) VALUES('Jason');
> INSERT INTO a (name) VALUES('Peter');
>
> CREATE TABLE b(row_id serial, id INT, name TEXT);
> INSERT INTO b (name) VALUES('Jason');
> INSERT INTO b (name) VALUES('Peter');
>
>
> WITH inserted AS (INSERT INTO a (name) SELECT b.name FROM b WHERE b.name = name RETURNING a.id)
>  UPDATE b SET id = inserted.id FROM inserted WHERE inserted.row_id = b.row_id;
>
> However this would not work for obvious reason:
>
> WHERE inserted.row_id = b.row_id is invalid because RETURNING clause cannot return row_id.
> What can be returned are only columns of 'a', but they are insufficient to identify matching records of 'b'.
>
> So the question is - what to put in WHERE clause to match RETURNING with rows being inserted from 'b'?
>
> Thanks!
>
> --
> Aleksandr Furmanov
>
>
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general


Re: INSERT RETURNING with values other than inserted ones.

From
Aleksandr
Date:
Thanks,
However I am not just replicating data from 'a' to 'b', I provided simplified example, in reality table 'b' keeps data
whichare going to be merged into 'a', some rows will be updated, some added. There is some other work has to be done on
'b'before merging into 'a' and that work relies on 'id' from a. 

On Jun 10, 2013, at 4:39 PM, Richard Dunks wrote:

> If you're just replicating the data from table A into table B, why does it need its own ID number? Wouldn't the table
AID suffice? 
>
> I'd recommend using the following:
>
> CREATE TABLE b AS ( SELECT * FROM a );
>
> This way, you only define the columns and insert the data once, then let Postgres do the rest for you. Obviously if
youneed to have a separate table B ID, you can alter as necessary.  
>
> Good luck,
> Richard Dunks
>
> On Jun 10, 2013, at 7:29 PM, Aleksandr Furmanov <aleksandr.furmanov@gmail.com> wrote:
>
>> Hello,
>> I want to insert new values into target table 'a' from source table 'b', and then update table 'b' with ids from
table'a', somewhat like: 
>>
>> CREATE TABLE a(id SERIAL, name TEXT);
>> INSERT INTO a (name) VALUES('Jason');
>> INSERT INTO a (name) VALUES('Peter');
>>
>> CREATE TABLE b(row_id serial, id INT, name TEXT);
>> INSERT INTO b (name) VALUES('Jason');
>> INSERT INTO b (name) VALUES('Peter');
>>
>>
>> WITH inserted AS (INSERT INTO a (name) SELECT b.name FROM b WHERE b.name = name RETURNING a.id)
>> UPDATE b SET id = inserted.id FROM inserted WHERE inserted.row_id = b.row_id;
>>
>> However this would not work for obvious reason:
>>
>> WHERE inserted.row_id = b.row_id is invalid because RETURNING clause cannot return row_id.
>> What can be returned are only columns of 'a', but they are insufficient to identify matching records of 'b'.
>>
>> So the question is - what to put in WHERE clause to match RETURNING with rows being inserted from 'b'?
>>
>> Thanks!
>>
>> --
>> Aleksandr Furmanov
>>
>>
>>
>> --
>> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
>> To make changes to your subscription:
>> http://www.postgresql.org/mailpref/pgsql-general



Re: INSERT RETURNING with values other than inserted ones.

From
David Johnston
Date:
Aleksandr Furmanov wrote
> Thanks,
> However I am not just replicating data from 'a' to 'b', I provided
> simplified example, in reality table 'b' keeps data which are going to be
> merged into 'a', some rows will be updated, some added. There is some
> other work has to be done on 'b' before merging into 'a' and that work
> relies on 'id' from a.

Three options:

1) CREATE TABLE a (id serial, name text, source_id_from_table_b integer);
and during INSERT provide which record on B caused the record on A to be
created.

2) Determine what can be used as a true primary key on both A and B; forgo
the use of SERIAL

3) Do whatever it is you need to do one record at a time within a pl/pgsql
function and capture the ID from B and the post-insert ID from A into local
variables to generate a temporary mapping for doing your other work.

I'd suggest #1; simply move the mapping column from "B" to "A" and perform
the linking during the insert but your simplified example provide no context
to evaluate if this will actually meet your needs.  The main concern is that
this basically models a 1-to-1(optional) relationship between A and B; such
that every record in A must exist in B (assuming you disallow NULL) but B
can have records that do not exist in A.  Whether multiple records in A can
share the same "source" record in B is undefined by can be made explicit by
the choice of INDEX that you create (UNIQUE or NORMAL).

David J.






--
View this message in context:
http://postgresql.1045698.n5.nabble.com/INSERT-RETURNING-with-values-other-than-inserted-ones-tp5758695p5758793.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.