Single Postgres request to update many records using local hash / array

I want to use a single query to update many records in my Postgres database using a hash or Ruby array, instead of iterating over each record and invoking a separate update.

# {:id => :color}
my_hash = {
  1 => 'red',
  2 => 'blue',
  3 => 'green'
}

As I do not want to do this, because it makes three consecutive requests:

my_hash.each do |id, color|
  MyModel.where(id: id).update_all(color: color)
end

How I want to do this:

MyModel.connection.execute <<-SQL
  UPDATE my_models
    SET color=something
    FROM somehow_using(my_hash)
    WHERE maybe_id=something
SQL
+4
source share
2 answers

You can use case:

update my_models
    set color = case id
        when 1 then 'red'
        when 2 then 'blue'
        when 3 then 'green'
    end;

or save the hash in a separate table:

create table my_hash (id int, color text);
insert into my_hash values
    (1, 'red'),
    (2, 'blue'),
    (3, 'green');

update my_models m
    set color = h.color
    from my_hash h
    where h.id = m.id;

Another option if you know how to choose a hash like jsonb:

with hash as (
    select '{"1": "red", "2": "blue", "3": "green"}'::jsonb h
    )
update my_models
    set color = value
    from hash, jsonb_each_text(h)
    where key::int = id;

OP ruby-fying klin :

sql = <<-SQL
with hash as (
  select '#{my_hash.to_json}'::jsonb h
)
update my_models
  set color = value
  from hash, jsonb_each_text(h)
  where key::int = id;
SQL

ActiveRecord::Base.connection.execute(sql)
+2

- . , , , , PG JSON.

ActiveRecord::Base.connection.execute(
  my_hash.collect{|id,color| "UPDATE my_models SET color=#{color} WHERE id=#{id};"}.join('')
)
# And don't forget to sanitize the :id and :color values
0

Source: https://habr.com/ru/post/1620646/


All Articles