Ecto support for Postgresql UPDATE… FROM… AS syntax

Hello! Anyone knows how to build such query using Ecto? I’m afraid neither of update_all or Ecto.Query.update syntax supports it:

    name = values.column_name
        (1, 'test one'),
        (2, 'test two'),
        (3, 'test three'),
        (4, 'test four')
) AS values (column_id,  column_name)
    values.column_id =

Source: Bulk Insert and Update in PostgreSQL | by akhouri | Medium


You can access the UPDATE...FROM... syntax by using a join in update_all

from(p in Posts, 
  join: c in Comments, on: c.post_id ==, 
  update: [set: [post_column: c.some_other_column]]
|> Repo.update_all([])

But Ecto doesn’t support value lists right now. So your exact example can’t be done.

For some background on why it is a join, this is essentially what Postgres does:

When a FROM clause is present, what essentially happens is that the target table is joined to the tables mentioned in the from_item list, and each output row of the join represents an update operation for the target table. When using FROM you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn’t join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.

This shows an alternative to value lists using unnest: Unnest for runtime sorted results | Benjamin Milde

json_to_recordset is also great, but I don’t have a good example ready.


Thanks for the help, I ended up using the join + unnest approach :slight_smile:

I could be cleaner with some macros but for now it works for my use cases, see the code here: accent/operations_update_all_dynamic.ex at master · mirego/accent · GitHub