Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do an update + join in PostgreSQL?

Basically, I want to do this:

update vehicles_vehicle v      join shipments_shipment s on v.shipment_id=s.id  set v.price=s.price_per_vehicle; 

I'm pretty sure that would work in MySQL (my background), but it doesn't seem to work in postgres. The error I get is:

ERROR:  syntax error at or near "join" LINE 1: update vehicles_vehicle v join shipments_shipment s on v.shi...                                   ^ 

Surely there's an easy way to do this, but I can't find the proper syntax. So, how would I write this In PostgreSQL?

like image 605
mpen Avatar asked Oct 23 '11 22:10

mpen


People also ask

How do you update a table using join in Postgres?

First, we specify the name of the table after the UPDATE keyword. We then set the new value of the column that we want to update. Using the FROM clause, we specify the joined table. Finally, we specify the conditions for the join in the WHERE clause.

Can you update a joined table?

SQL Server UPDATE JOIN syntaxFirst, specify the name of the table (t1) that you want to update in the UPDATE clause. Next, specify the new value for each column of the updated table. Then, again specify the table from which you want to update in the FROM clause.


2 Answers

The UPDATE syntax is:

 [ WITH [ RECURSIVE ] with_query [, ...] ] UPDATE [ ONLY ] table [ [ AS ] alias ]     SET { column = { expression | DEFAULT } |           ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...]     [ FROM from_list ]     [ WHERE condition | WHERE CURRENT OF cursor_name ]     [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] 

In your case I think you want this:

UPDATE vehicles_vehicle AS v  SET price = s.price_per_vehicle FROM shipments_shipment AS s WHERE v.shipment_id = s.id  
like image 75
Mark Byers Avatar answered Sep 28 '22 04:09

Mark Byers


The answer of Mark Byers is the optimal in this situation. Though in more complex situations you can take the select query that returns rowids and calculated values and attach it to the update query like this:

with t as (   -- Any generic query which returns rowid and corresponding calculated values   select t1.id as rowid, f(t2, t2) as calculatedvalue   from table1 as t1   join table2 as t2 on t2.referenceid = t1.id ) update table1 set value = t.calculatedvalue from t where id = t.rowid 

This approach lets you develop and test your select query and in two steps convert it to the update query.

So in your case the result query will be:

with t as (     select v.id as rowid, s.price_per_vehicle as calculatedvalue     from vehicles_vehicle v      join shipments_shipment s on v.shipment_id = s.id  ) update vehicles_vehicle set price = t.calculatedvalue from t where id = t.rowid 

Note that column aliases are mandatory otherwise PostgreSQL will complain about the ambiguity of the column names.

like image 44
Alvin Avatar answered Sep 28 '22 06:09

Alvin