Update a column of a table with a column of another table in PostgreSQL

Your UPDATE query should look like this:

UPDATE table2 t2
SET    val2 = t1.val1
FROM   table1 t1
WHERE  t2.table2_id = t1.table2_id
AND    t2.val2 IS DISTINCT FROM t1.val1;  -- optional, see below

The way you had it, there was no link between individual rows of the two tables. Every row would be fetched from table1 for every row in table2. This made no sense (in an expensive way) and also triggered the syntax error, because a subquery expression in this place is only allowed to return a single value.

I fixed this by joining the two tables on table2_id. Replace that with your actual join condition.

I rewrote the UPDATE to join in table1 (with the FROM clause) instead of running correlated subqueries, because that is typically faster.
It also prevents that table2.val2 is nullified where no matching row is found in table1. Instead, nothing happens to such rows with this form of the query.

You can add table expressions to the FROM list like you would in a plain SELECT (tables, subqueries, set-returning functions, …). The manual:

from_item

A table expression allowing columns from other tables to appear in the WHERE condition and update expressions. This uses the same
syntax as the FROM clause of a SELECT statement; for example,
an alias for the table name can be specified. Do not repeat the target
table as a from_item unless you intend a self-join (in which
case it must appear with an alias in the from_item).

The final WHERE clause prevents updates that wouldn’t change anything – at almost full cost but no gain (exotic exceptions apply). If both old and new value are guaranteed to be NOT NULL, simplify to:

AND   t2.val2 <> t1.val1

See:

Leave a Comment