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

时间:2009-08-27 23:10:30

标签: sql ruby-on-rails activerecord

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

例如:

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

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

11 个答案:

答案 0 :(得分:186)

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

对于Rails 2:

ActiveRecord::Base.connection.instance_variable_set :@logger, Logger.new(STDOUT)

对于Rails 3.0.x:

ActiveRecord::Base.logger = Logger.new(STDOUT)

对于Rails> = 3.1.0,这在控制台中默认已经完成。万一它太吵了,你想关掉它你可以这样做:

ActiveRecord::Base.logger = nil

答案 1 :(得分:78)

答案 2 :(得分:22)

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

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

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

答案 3 :(得分:16)

只需使用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"

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

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

答案 4 :(得分:11)

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

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

修改construct_finder_sql was removed in Rails 5.1.0.beta1

答案 5 :(得分:11)

这是我通常在控制台中生成SQL的方法

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

首次启动控制台时必须执行此操作,如果在键入某些代码后执行此操作,则它似乎无法正常工作

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

答案 6 :(得分:10)

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

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

这将在你去的时候将SQL语句输出到你的irb会话中。

编辑:很抱歉,这仍将执行查询,但它是我所知道的最接近的。

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

答案 7 :(得分:3)

我看到它使用的sql的典型方法是在sql中引入一个“bug”,然后你会得到一条错误消息吐出到有问题的sql的普通记录器(和web屏幕)。无需找到stdout的去向......

答案 8 :(得分:2)

试试show_sql plugin。该插件使您可以在不运行的情况下打印SQL

SampleModel.sql(:select => "DISTINCT(*)", :conditions => ["`date` > #{self.date}"], :limit => 1, :order => '`date`', :group => "`date`")

答案 9 :(得分:1)

您可以更改连接的日志方法以引发异常,从而阻止查询运行。

这完全是黑客攻击,但它似乎对我有用(Rails 2.2.2,MySQL):

module ActiveRecord
  module ConnectionAdapters
    class AbstractAdapter
      def log_with_raise(sql, name, &block)
        puts sql
        raise 'aborting select' if caller.any? { |l| l =~ /`select'/ }
        log_without_raise(sql, name, &block)
      end
      alias_method_chain :log, :raise
    end
  end
end

答案 10 :(得分:0)

在Rails 3中,您可以将此行添加到config / environments / development.rb

config.active_record.logger = Logger.new(STDOUT)

然而,它将执行查询。但有一半得到了回答: