【问题标题】:Mass/bulk update in rails without using update_all with a single query?在 Rails 中进行大规模/批量更新而不使用 update_all 和单个查询?
【发布时间】:2017-06-13 05:35:13
【问题描述】:

我想使用单个查询活动记录来更新多行。我不必使用 update_all 因为它跳过了验证。有没有办法在 Rails 活动记录中做到这一点?

【问题讨论】:

  • 您不能在单个查询上执行此操作,因为验证应用于您的模型实例 .. 不是在集合上 .. 您可以遍历所有项目并在 begin 块内运行 update_attributes 并救援验证失败时

标签: sql ruby-on-rails activerecord


【解决方案1】:

可以使用 activerecord-import gem 实现不使用 update_all 的大规模更新。 更多信息请参考thisgem。 带有detail的方法。

示例: 假设有一个名为“Services”的表有一个“booked”列。我们想在循环外使用 gem 更新它的值。

services.each do |service| 
 service.booked = false 
 service.updated_at = DateTime.current if service.changed?
end


ProvidedService.import services.to_ary, on_duplicate_key_update: { columns: %i[booked updated_at] }

默认情况下,活动记录导入不会更新“updated_at”列。所以我们必须明确地更新它。

【讨论】:

    【解决方案2】:

    如果您想在不实例化模型的情况下更新多条记录,update_all 方法应该可以解决问题:

    使用给定的详细信息更新当前关系中的所有记录。此方法构造单个 SQL UPDATE 语句并将其直接发送到数据库。它不会实例化涉及的模型,也不会触发 Active Record 回调或验证。但是,传递给 #update_all 的值仍然会经过 Active Record 的正常类型转换和序列化。

    例如:

    # Update all books with 'Rails' in their title
    Book.where('title LIKE ?', '%Rails%').update_all(author: 'David')
    

    据我了解,它甚至接受一个数组作为参数,允许我们提供不同的哈希值以按照相应的顺序更新不同的记录,就像在 SQL UPDATE 语句中一样。如果我错了,请纠正我。

    【讨论】:

    • 它接受一个数组作为参数,但它不允许你提供不同的哈希值来更新不同的记录。我无法弄清楚它到底做了什么,所以我会避免那样使用它=)
    【解决方案3】:

    听起来您正在寻找Update records - 来自文档更新多条记录;不同的col有不同的数据

    你可以像这个例子那样做:

    people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
    Person.update(people.keys, people.values)
    

    【讨论】:

    • 但是对于每条记录,它都会触发一个单独的更新查询,所以我想要的是所有更新都应该只触发一个查询。
    • 不,这只会为您的所有记录触发一个查询Person.update(people.keys, people.values)
    • @RahulOjha 如果你对我的回答感到满意,那就改正并投票
    • @MayurShah 可悲的是,即使在您提供的文档和链接中,他们也提到他们将对每条记录进行一次查询:For every record, there will be a query sent(在您提供的链接中)
    • 是的,它在内部一个一个地执行,但是它减少了执行的时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    相关资源
    最近更新 更多