Sometimes I want to update lots of rows at once, but with different data for each key or combination of fields.
In PostgreSQL, it works like this:
UPDATE my_table
SET my_table.value = input.value
FROM (VALUES (1, 'abc'), (2, 'def')) AS input(id, value)
and in MySQL, it should work similarly with multiple tables in the list:
UPDATE my_table, (VALUES ROW(1, 'abc'), ROW(2, 'def')) AS input(id, value)
SET my_table.value = input.value
(I haven't tested either but they should be theoretically possible).
Since Ecto.Query can not contain multiple tables in the from clause, which you can work around with lateral joins in select queries, I thought that maybe there could be a new clause especially for updates that's similar to joins in that it can either contain another table, or another new feature, a VALUES expression.
The above queries could then look like this in ecto DSL:
values = Ecto.Query.values([%{id: 1, value: "abc"}, %{id: 2, value: "def"}])
query = from(m in MyTable, update: [set: [value: as(:input).value], from: values, as: :input], where: as(:input).id ==
m.id)
Repo.update_all(query, [])
Maybe there's a simpler way to write it or it can already be done.
The proposal with the values() function could also be useful in other queries.