Eki*_*bal 11 sql postgresql activerecord ruby-on-rails-3 ruby-on-rails-4
我曾经有过如下查询:
MyModel.where(id: ids)
Run Code Online (Sandbox Code Playgroud)
哪个生成sql查询如:
SELECT "my_models".* FROM "my_models"
WHERE "my_models"."id" IN (1, 28, 7, 8, 12)
Run Code Online (Sandbox Code Playgroud)
现在我想改为使用ANY
而不是IN
.我创造了这个:
MyModel.where("id = ANY(VALUES(#{ids.join '),('}))"
Run Code Online (Sandbox Code Playgroud)
现在,当我使用空数组时,ids = []
我得到以下错误:
MyModel Load (53.0ms) SELECT "my_models".* FROM "my_models" WHERE (id = ANY(VALUES()))
ActiveRecord::JDBCError: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
ActiveRecord::StatementInvalid: ActiveRecord::JDBCError: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
Position: 75: SELECT "social_messages".* FROM "social_messages" WHERE (id = ANY(VALUES()))
from arjdbc/jdbc/RubyJdbcConnection.java:838:in `execute_query'
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 37
IN
表达式有两种变体:
同样,两个变体与ANY
构造:
子查询适用于任何一种技术,但对于每种技术的第二种形式,IN
需要一个值列表(如标准SQL中所定义),同时= ANY
需要一个数组.
ANY
是一个后来更通用的补充,它可以与任何返回布尔值的二元运算符组合.IN
烧伤了一个特例ANY
.实际上,它的第二种形式是在内部重写的:
IN
被改写后= ANY
NOT IN
重写<> ALL
检查EXPLAIN
输出以查找任何查询以便自己查看.这证明了两件事:
IN
永远不会快于= ANY
.= ANY
不会快得多.选择应该由更容易提供的内容决定:值列表或数组(可能是数组文字 - 单个值).
如果您要传递的ID仍然来自数据库,那么直接选择它们(子查询)或将源表集成到查询中JOIN
(如@mu注释)则更有效.
要从客户端传递一长串值并获得最佳性能,请使用数组,unnest()
然后使用VALUES
(如@PinnyM注释)将其作为表表达式提供.更多:
在存在NULL值的情况下,JOIN
通常是错误的选择并且IN
是正确的(也更快):
= ANY
对于数组表达式,Postgres接受:
要避免无效的类型转换,您可以显式转换:
ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]
Run Code Online (Sandbox Code Playgroud)
有关:
或者你可以使用一个= ANY
参数创建一个Postgres函数,该函数接受各个参数并从中形成一个数组:
假设ARRAY[1,2,3]
是'{1,2,3}'
:
MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})
Run Code Online (Sandbox Code Playgroud)
但我只是涉足Ruby.@mu在此相关答案中提供了详细说明:
归档时间: |
|
查看次数: |
13937 次 |
最近记录: |