Thanks Jeremy. I continued to be impressed with the Sequel library! For anyone else who wants it... not sure if this has a place in the library but it is much more straight-forward and faster than iterating through records on migrations or using complicated insert_conflict logic.
Here is what I have so far... please test yourself as it's not battle tested! # Use like this: User.batch_update([[{id: 4}, {full_name: "New Full Name"}]]) def self.batch_update(data_lookup, return_sql: false) if data_lookup.present? lookup_columns, update_columns = data_lookup.first.map(&:keys) from, to = Sequel[:data], Sequel[table_name] conditions = lookup_columns.each.with_object({}) { |col, h| h[to[col]] = from[col] } updates = update_columns.each.with_object({}) { |col, h| h[col] = from[col] } values = data_lookup.map { |l, u| l.values + u.values } ds = db. from( to.value.to_sym, db.values(values).as(from.value.to_sym, [*lookup_columns, *update_columns]) ). where(conditions) ds.send(return_sql ? :update_sql : :update, updates) end end On Wednesday, August 9, 2023 at 4:24:47 PM UTC-7 Jeremy Evans wrote: > On Wed, Aug 9, 2023 at 11:35 AM aryk....@gmail.com <aryk....@gmail.com> > wrote: > >> Hi Jeremy, >> >> I saw some historical posts about batch updates like this one: >> >> https://groups.google.com/g/sequel-talk/c/uV7PRbEvQj0/m/lCvZaLx8AAAJ >> >> It feels a little "hacky" to say insert this record with a unique primary >> key that already exists...when you get an error, then update it. >> >> I've been using a solution like this: >> >> run <<-SQL >> update user_expo_push_tokens as uept set -- postgres FTW >> device_id = ud2.device_id >> from (values >> #{updates.join(", ")} >> ) as ud2(installation_id, device_id) >> where ud2.installation_id = uept.installation_id; >> SQL >> >> This also works in the case where the values are not a primary key or >> have a unique index to throw the "on duplicate key update" logic. >> >> Is there a way to accomplish this without having to drop to straight sql? >> > > I think this will work: > > DB.from(Sequel.as(:user_expo_push_tokens, :uept), > DB.values(updates).as(:ud2, [:installation_id, :device_id])). > where{{ud2[:installation_id]=>uept[:installation_id]}}. > update(:device_id => Sequel[:ud2][:device_id]) > > SQL: > > UPDATE "user_expo_push_tokens" AS "uept" > SET "device_id" = "ud2"."device_id" > FROM (VALUES ...) AS "ud2"("installation_id", "device_id") > WHERE ("ud2"."installation_id" = "uept"."installation_id") > > It depends on what "updates" is supposed to be. > > Thanks, > Jeremy > -- You received this message because you are subscribed to the Google Groups "sequel-talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to sequel-talk+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sequel-talk/1d21ebcf-8ec2-4fb9-b6b7-229c019fe686n%40googlegroups.com.