ActiveRecord vs SQL原始查询?

时间:2016-08-26 11:06:13

标签: ruby-on-rails activerecord

ActiveRecord和编写原始查询之间有什么区别。  在哪种情况下,应该采用在rails app中编写原始查询。

2 个答案:

答案 0 :(得分:4)

关键的区别在于,ActiveRecord可以通过使用更高级别的抽象来提高您​​的工作效率。

通过抽象出DBMS之间的一些差异,它还使您的代码更具可移植性。

如果您不注意ActiveRecord生成的查询,这种抽象是有代价的,可能会导致性能问题。

  

在哪种情况下应该采用在rails app中编写原始查询?

当需要完成手头的工作时。例如,这可以使用Postgres扩展ILIKE

# case insensitive search:
@user = User.where('users.name ILIKE ?', params[:name])

或者当您需要执行复杂的连接或其他性能关键操作时。像这个例子一样,每个父母获取一些相关记录。听起来很简单但在ActiveRecord中很难做到。

class Observation < ActiveRecord::Base
  belongs_to :station

  # ...

  def self.pluck_from_each_station(limit = 1)
    ActiveRecord::Base.connection.execute(%Q{
      SELECT o.id
      FROM   stations s
      JOIN LATERAL (
         SELECT id, created_at
         FROM   observations
         WHERE  station_id = s.id  -- lateral reference
         ORDER  BY created_at DESC
         LIMIT  #{limit}
      ) o ON TRUE
      ORDER BY s.id, o.created_at DESC;
    }).field_values('id')
  end
end

最后,如果您不知道如何使用ActiveRecord执行操作,通常最好先编写一些带有测试支持的SQL,然后再返回并重构。

@users = User.where("occupation NOT IN(?)", params[:blacklist])) # @todo fix

然后你可以将其重构为:

@users.where.not(occupation: params[:blacklist])

答案 1 :(得分:0)

ActiveRecord大部分时间都会为您提供服务,但在某些情况下您需要编写原始sql。值得注意的是,ActiveRecord查询也可以以类似sql的方式编写。例如,您可以写:

User.where(name: "Person A")

或者您可以使用稍微类似SQL的语法编写它:

User.where("name = ?", "Person A")
User.where("name LIKE ?", "%Person A%")

您可能想要编写原始SQL的原因之一是当您尝试访问无法通过ActiveRecord方法访问的内容时,例如has_and_belongs_to_many关联中的连接表。