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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1344232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 03:22:02  来源:igfitidea点击:

How can I see the SQL that will be generated by a given ActiveRecord query in Ruby on Rails

sqlruby-on-railsactiverecord

提问by rswolff

I would like to see the SQL statement that a given ActiveRecord Query will generate. I recognize I can get this information from the log after the query has been issued, but I'm wondering if there is a method that can be called on and ActiveRecord Query.

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

For example:

例如:

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

I would like to open the irb console and tack a method on the end that would show the SQL that this query will generate, but not necessarily execute the query.

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

采纳答案by John F. Miller

When last I tried to do this there was no official way to do it. I resorted to using the function that findand its friends use to generate their queries directly. It is private API so there is a huge risk that Rails 3 will totally break it, but for debugging, it is an ok solution.

上次我尝试这样做时,没有官方方法可以做到这一点。我求助于使用find它及其朋友用来直接生成查询的函数。它是私有 API,因此 Rails 3 完全破坏它的风险很大,但对于调试,这是一个不错的解决方案。

The method is construct_finder_sql(options)(lib/active_record/base.rb:1681) you will have to use sendbecause it is private.

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

Edit: construct_finder_sqlwas removed in Rails 5.1.0.beta1.

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

回答by gtd

Similar to penger's, but works anytime in the console even after classes have been loaded and the logger has been cached:

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

For Rails 2:

对于 Rails 2:

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

For Rails 3.0.x:

对于 Rails 3.0.x:

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

For Rails >= 3.1.0 this is already done by default in consoles. In case it's too noisy and you want to turn it offyou can do:

对于 Rails >= 3.1.0,这已经在控制台中默认完成了。如果它太吵并且您想将其关闭,您可以这样做:

ActiveRecord::Base.logger = nil

回答by pathdependent

Stick a puts query_object.classsomewhere to see what type of object your working with, then lookup the docs.

贴在puts query_object.class某个地方以查看您使用的对象类型,然后查找文档。

For example, in Rails 3.0, scopes use ActiveRecord::Relationwhich has a #to_sqlmethod. For example:

例如,在 Rails 3.0 中,作用域使用ActiveRecord::Relationwhich 有一个#to_sql方法。例如:

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

Then, somewhere you can do:

然后,您可以在某处执行以下操作:

puts Contact.frequently_contacted.to_sql

回答by Akshat

This may be an old question but I use:

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

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

The explainmethod will give quite a detailed SQL statement on what its going to do

explain方法将提供非常详细的 SQL 语句,说明其将要执行的操作

回答by Itai Sagi

just use to_sqlmethod and it'll output the sql query that will be run. it works on an active record relation.

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

when doing find, it won't work, so you'll need to add that id manually to the query or run it using where.

这样做时find,它将不起作用,因此您需要将该 ID 手动添加到查询中或使用 where 运行它。

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

回答by penger

This is what I usually do to get SQL generated in console

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

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

You have to do this when you first start the console, if you do this after you have typed some code, it doesn't seem to work

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

Can't really take credit for this, found it long time ago from someone's blog and can't remember whose it is.

不能真正相信这一点,很久以前从某人的博客中找到的,不记得是谁的。

回答by nitecoder

Create a .irbrc file in your home directory and paste this in:

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

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

That will output SQL statements into your irb session as you go.

这将在您进行时将 SQL 语句输出到您的 irb 会话中。

EDIT: Sorry that will execute the query still, but it's closest I know of.

编辑:对不起,它仍然会执行查询,但它是我所知道的最接近的。

EDIT: Now with arel, you can build up scopes/methods as long as the object returns ActiveRecord::Relation and call .to_sql on it and it will out put the sql that is going to be executed.

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

回答by rogerdpack

My typical way to see what sql it uses is to introduce a "bug" in the sql, then you'll get an error messages spit out to the normal logger (and web screen) that has the sql in question. No need to find where stdout is going...

我查看它使用的 sql 的典型方法是在 sql 中引入一个“错误”,然后您将收到一条错误消息,该消息会发送到具有相关 sql 的普通记录器(和网络屏幕)。无需查找标准输出的去向...

回答by Harish Shetty

Try the show_sql plugin. The plugin enables you to print the SQL without running it

试试show_sql 插件。该插件使您无需运行即可打印 SQL

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

回答by also

You could change the connection's log method to raise an exception, preventing the query from being run.

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

It's a total hack, but it seems to work for me (Rails 2.2.2, MySQL):

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