如何在 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
How can I see the SQL that will be generated by a given ActiveRecord query in Ruby on Rails
提问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 find
and 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 send
because it is private.
该方法是construct_finder_sql(options)
( lib/active_record/base.rb:1681
) 您必须使用,send
因为它是私有的。
Edit: construct_finder_sql
was 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.class
somewhere 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::Relation
which has a #to_sql
method. For example:
例如,在 Rails 3.0 中,作用域使用ActiveRecord::Relation
which 有一个#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 explain
method will give quite a detailed SQL statement on what its going to do
该explain
方法将提供非常详细的 SQL 语句,说明其将要执行的操作
回答by Itai Sagi
just use to_sql
method 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