2

我有一个 ActiveRecord 模型数组,我想重新编号一列并批量更新它们。代码如下所示:

rules = subject.email_rules.order(:number)
rules.each_with_index do |rule, index|
  rule.number = index + 1
end

EmailRule.update(rules.map(&:id), rules.map { |r| { number: r.number } })

但这会创建 N 个 SQL 语句,我想要 1,有没有办法做到这一点?

4

2 回答 2

2

假设你正在使用你可以使用row_number的 postgres 和看起来有点奇怪的UPDATE/FROM结构。这是基本版本:

UPDATE email_rules target 
SET number = src.idx
FROM (
  SELECT 
    email_rules.id,
    row_number() OVER () as idx
    FROM email_rules
) src
WHERE src.id = target.id

您可能需要在 a 上确定范围subject,当然还包括按数字排列的顺序,如下所示:

UPDATE email_rules target 
SET number = src.idx
FROM (
  SELECT 
    email_rules.id,
    row_number() OVER (partition by subject_id) as idx
    FROM email_rules
    ORDER BY number ASC
) src
WHERE src.id = target.id

(假设subject_id是关联主题/电子邮件规则的外键)

于 2017-08-07T13:46:41.437 回答
1

您的另一种选择是将所有交互放在一个事务中,它至少会在最后进行一次提交,从而使其更快。

ActiveRecord::Base.transaction do
  ...
end
于 2017-08-07T13:25:28.070 回答