156

I'm trying to do something like this in postgres:

  • UPDATE table1 SET (col1, col2) = (SELECT col2, col3 FROM othertable WHERE othertable.col1 = 123);

  • INSERT INTO table1 (col1, col2) VALUES (SELECT col1, col2 FROM othertable)

But point 1 is not possible even with postgres 9.0 as mentioned in the docs (http://www.postgresql.org/docs/9.0/static/sql-update.html)

Also point 2 seems not working. i'm getting the following error: subquery must return only one column.

Hope somebody has a workaround for me. otherwise the queries will take a looot of time :(.

FYI: I'm trying to select different columns from several tables and store them into a temporary table, so that another application can easily fetch the prepared data.

4 Answers 4

252

For the UPDATE

Use:

UPDATE table1 SET col1 = othertable.col2, col2 = othertable.col3 FROM othertable WHERE othertable.col1 = 123; 

For the INSERT

Use:

INSERT INTO table1 (col1, col2) SELECT col1, col2 FROM othertable 

You don't need the VALUES syntax if you are using a SELECT to populate the INSERT values.

Sign up to request clarification or add additional context in comments.

1 Comment

Is it possible to combine Update & Insert so that if one fails, the other will be used without throwing an error (independently for each row). I think that would be a more complete solution to the question (for example: stackoverflow.com/a/6527838/781695)
41

OMG Ponies's answer works perfectly, but just in case you need something more complex, here is an example of a slightly more advanced update query:

UPDATE table1 SET col1 = subquery.col2, col2 = subquery.col3 FROM ( SELECT t2.foo as col1, t3.bar as col2, t3.foobar as col3 FROM table2 t2 INNER JOIN table3 t3 ON t2.id = t3.t2_id WHERE t2.created_at > '2016-01-01' ) AS subquery WHERE table1.id = subquery.col1; 

2 Comments

perfect. this works best wherein you need to pick a subset based on a condition involving the updated table itself.
@David Namenyi can you explain this query?
20
UPDATE table1 SET (col1, col2) = (col2, col3) FROM othertable WHERE othertable.col1 = 123; 

Comments

1

It's always best to run query in transaction first so that you can revert it if result is differ from what you want to achieve, here is what I used for above problem

BEGIN; -- beginning of transaction UPDATE admin_layer.mh_village vill SET (dtncode, dtname, crncode, crname, subdname, thncode) = (n.dtncode, n.dtname, n.crncode, n.crname, n.subdname, n.thncode) FROM admin_layer.update_gp_codes n WHERE n.vincode = vill.vincode AND vill.phase = 2; -- Check result with select query, because you are in transaction -- it will show you actual result just like real update SELECT id, stncode, stname, dvncode, dvname, dtncode, dtname, crncode, crname, subdname, thncode FROM admin_layer.mh_village WHERE phase = 2 AND gpncode is null -- ROLLBACK; -- if you want to revert it uncomment -- COMMIT; -- if result is what you want 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.