首页 文章

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

提问于
浏览
103

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

例如:

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

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

11 回答

  • 1

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

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

    Editconstruct_finder_sql was removed in Rails 5.1.0.beta1 .

  • 2

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

    对于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,默认情况下已在控制台中完成 . 万一它太吵了你想要 turn it off 你可以这样做:

    ActiveRecord::Base.logger = nil
    
  • 74

    坚持 puts query_object.class 某处查看您正在使用的对象类型,然后查找文档 .

    例如,在Rails 3.0中,作用域使用 ActiveRecord::Relation ,它具有 #to_sql 方法 . 例如:

    class Contact < ActiveRecord::Base
      scope :frequently_contacted, where('messages_count > 10000')
    end
    

    然后,你可以在某处做:

    puts Contact.frequently_contacted.to_sql
    
  • 2

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

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

    explain 方法将提供关于它将要执行的操作的详细SQL语句

  • 11

    只需使用 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 时,它赢得了't work, so you' ll需要手动将该id添加到查询中或使用where运行它 .

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

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

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

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

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

  • 14

    在主目录中创建.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 .

  • 0

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

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

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

  • 10

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

    这是一个彻底的黑客,但它似乎对我有用(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
    
  • 21

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

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

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

相关问题