如何在Ruby on Rails中查看由给定的ActiveRecord查询生成的SQL

rsw*_*lff 112 sql activerecord ruby-on-rails

我想看一个给定的ActiveRecord Query将生成的SQL语句.我发现在查询发出后我可以从日志中获取此信息,但我想知道是否有可以调用的方法和ActiveRecord Query.

例如:

SampleModel.find(:all, :select => "DISTINCT(*)", :conditions => ["`date` > #{self.date}"], :limit => 1, :order => '`date`', :group => "`date`")
Run Code Online (Sandbox Code Playgroud)

我想打开irb控制台并在最后添加一个方法,该方法将显示此查询将生成的SQL,但不一定执行查询.

gtd*_*gtd 188

与penger相似,但即使在加载了类并且缓存了记录器后,也可以在控制台中随时工作:

对于Rails 2:

ActiveRecord::Base.connection.instance_variable_set :@logger, Logger.new(STDOUT)
Run Code Online (Sandbox Code Playgroud)

对于Rails 3.0.x:

ActiveRecord::Base.logger = Logger.new(STDOUT)
Run Code Online (Sandbox Code Playgroud)

对于Rails> = 3.1.0,默认情况下已在控制台中完成.如果它太嘈杂而你想关掉它你可以做:

ActiveRecord::Base.logger = nil
Run Code Online (Sandbox Code Playgroud)

  • 他们把它移到Rails 3更合理的地方......看看我的更新版本. (2认同)
  • 这并没有回答以下问题:如何在调试时显示特定查询的 sql,而不运行查询。 (2认同)

pat*_*ent 85

坚持一个puts query_object.class地方,看看你正在使用什么类型的对象,然后查找文档.

例如,在Rails 3.0中,范围使用ActiveRecord::Relation具有#to_sql方法的范围.例如:

class Contact < ActiveRecord::Base
  scope :frequently_contacted, where('messages_count > 10000')
end
Run Code Online (Sandbox Code Playgroud)

然后,你可以在某处做:

puts Contact.frequently_contacted.to_sql
Run Code Online (Sandbox Code Playgroud)

  • 注意:如果你的关系中有`includes`,你就不会得到所有的SQL (5认同)
  • 为什么这个答案没有被投票?对于Rails 3来说,这是一个更好的答案 - 只需将".to_sql"放在最后,就可以得到任何AR :: Relation语句的结果.这个问题也提供了答案:http://stackoverflow.com/questions/3814738/how-can-i-get-sql-statement-created-by-activerecordfind-without-actually-execut (3认同)
  • @BarryKelly为什么? (3认同)

Aks*_*hat 23

这可能是一个老问题,但我使用:

SampleModel.find(:all,
                 :select => "DISTINCT(*)",
                 :conditions => ["`date` > #{self.date}"], 
                 :limit=> 1, 
                 :order => '`date`',
                 :group => "`date`"
                 ).explain
Run Code Online (Sandbox Code Playgroud)

explain方法将提供关于它将要做什么的非常详细的SQL语句

  • 它还会运行查询,这可能不是人们想要的,只是为了记录. (3认同)

Ita*_*agi 17

只需使用to_sql方法,它将输出将运行的SQL查询.它适用于活跃的记录关系.

irb(main):033:0> User.limit(10).where(:username => 'banana').to_sql
=> "SELECT  "users".* FROM "users"  WHERE "users"."username" = 'banana'
LIMIT 10"
Run Code Online (Sandbox Code Playgroud)

在执行时find,它将无法工作,因此您需要手动将该ID添加到查询中或使用where运行它.

irb(main):037:0* User.where(id: 1).to_sql
=> "SELECT "users".* FROM "users"  WHERE "users"."id" = 1"
Run Code Online (Sandbox Code Playgroud)


Joh*_*ler 11

当我最后一次尝试这样做时,没有正式的方法来做到这一点.我使用了它find和朋友用来直接生成查询的函数.它是私有API,因此Rails 3将完全破坏它的风险很大,但是对于调试来说,这是一个很好的解决方案.

方法是construct_finder_sql(options)(lib/active_record/base.rb:1681)你必须使用,send因为它是私有的.

编辑:construct_finder_sql 已在Rails 5.1.0.beta1中删除.

  • 在Rails 3中,确实删除了construct_finder_sql` (4认同)

pen*_*ger 11

这是我通常在控制台中生成SQL所做的事情

-> script/console
Loading development environment (Rails 2.1.2)
>> ActiveRecord::Base.logger = Logger.new STDOUT
>> Event.first
Run Code Online (Sandbox Code Playgroud)

首次启动控制台时必须执行此操作,如果在键入某些代码后执行此操作,则它似乎不起作用

真的不能归功于此,很久以前从某人的博客发现并且不记得它是谁.


nit*_*der 10

在主目录中创建.irbrc文件并将其粘贴到:

if ENV.include?('RAILS_ENV') && !Object.const_defined?('RAILS_DEFAULT_LOGGER')
  require 'logger'
  RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
end
Run Code Online (Sandbox Code Playgroud)

这会将SQL语句输出到你的irb会话中.

编辑:抱歉,仍然会执行查询,但它是我所知道的最接近的.

编辑:现在使用arel,只要对象返回ActiveRecord :: Relation并在其上调用.to_sql,就可以构建范围/方法,它将输出将要执行的sql.


rog*_*ack 5

我查看其使用的sql的典型方法是在sql中引入“错误”,然后您会得到一条错误消息,该错误消息会被发送到具有该sql的普通记录器(和Web屏幕)。无需找到stdout的去向...

  • 壮观但最快的解决方案:) (2认同)