sql - 在 Rails 中使用连接执行 update_all

标签 sql ruby-on-rails ruby scope sql-update

在这种情况下,Rails 对原始 SQL 的抽象让我抓狂。在 MySQL 中我可以这样做:

UPDATE FROM tasks AS t 
LEFT JOIN projects as p 
ON t.project_id = p.id 
SET t.invoice_id = 7
WHERE p.organization_id == 42
AND t.invoice_id IS NULL

我如何在 Rails 3.0.1 中使用预先加载来做到这一点?我已经尝试了以下所有方法:

Tasks.joins(:project).where('projects.organization_id' => 42, :invoice_id => nil).update_all( :invoice_id => 7 )

以及上述的所有变体。所有要么给出错误,要么没有找到任何东西。

然后我尝试使用 scope :

Task.scope :find => {:joins => :project, :conditions => ["projects.organization_id == ? AND invoice_id IS NULL", @organization.id] } do
  Task.update_all :invoice_id => @invoice.id
end

这个给了我错误 undefined method 'to_sym' for #<Hash:0x1065c6438> .

我在这上面花了太多时间,只是为了复制一个简单的 SQL 查询。请帮忙!


编辑:绕过 n+1 的临时错误解决方案:

task_ids = Task.select('tasks.id').joins(:project).where('projects.organization_id' => @organization.id, :invoice_id => nil).collect{|t| t.id}
Task.update_all ['invoice_id = ?', @invoice.id], ["id in (#{task_ids.join(',')})"]

最佳答案

"UPDATE FROM"不是标准的 SQL,因此如果 Active Record 不直接支持它也就不足为奇了。然而,Active Record 确实为您提供了一种绕过其抽象并直接发出 SQL 的方法,用于那些您必须执行它不支持的操作的时候。模型内部:

sql = "UPDATE FROM tasks AS t 
LEFT JOIN projects as p 
ON t.project_id = p.id 
SET t.invoice_id = 7
WHERE p.organization_id == 42
AND t.invoice_id IS NULL"
connection.update_sql(sql)

ActiveRecord::Base 也有一个“select_by_sql”方法,让您的非标准选择语句返回常规事件记录模型实例。

关于sql - 在 Rails 中使用连接执行 update_all,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6831069/

相关文章:

ruby-on-rails - 升级到 Rails 3 : Problem with routes

sql - 使用其他表的条件更新表的最有效方法?

mysql - 在sql查询中复制行

ruby-on-rails - 没有要加载的文件 -- active_support/core_ext (LoadError)

ruby-on-rails - 要求 'rubygems'不起作用

Ruby Selenium Webdriver 拖放

ruby - AWS lambda : Ruby function failing to load gem

SQL - 添加计数 if 语句

sql - 在一个事务 SQL 中删除和插入

javascript - 无法使 JS 插件与 Rails 5.1 和 Yarn 一起工作