[英]Using WHERE IN with Rails prepared statement syntax
讓我們說我有一個數組(從客戶端收到)的ids:
myArray = [1,5,19,27]
我想返回(次要)ID在該列表中的所有項目。
在SQL中,這將是:
SELECT * FROM Items WHERE id IN (1,5,19,27)
我知道我能做到:
Item.where(id: [1,5,9,27])
,
但是,查詢的時間越長,使用准備好的語句語法Item.where('myAttrib = ? AND myOtherAttrib <> ? AND myThirdAttrib = ?', myVal[0], myVa[1], myVal[2])
考慮到這一點,我想要的是以下內容:
Item.where('id IN ?', myArray)
但是,這會產生語法錯誤:
ActiveRecord::StatementInvalid: PG::Error: ERROR: syntax error at or near "1" LINE 1: SELECT "items".* FROM "items" WHERE (id in 1,2,3,4)
我該如何解決這個問題? 使用IN
表達式的預准備語句語法的正確方法是什么。
我最終使用:
Item.where('id IN (?)', myArray)
您需要將查詢更改為以下內容:
Item.where('id = ?', myArray)
如果myArray實際上是一個數組,ActiveRecord會將其轉換為IN子句。
使用原始sql的問題在於您丟失了由Rails和AREL免費提供的列名的自動命名空間。
使用原始sql可以在組合和合並查詢或范圍時或在進行連接時開始導致問題。
無需使用原始sql來使用IN
:
Item.where(:id => myArray) # SELECT * FROM items WHERE id IN (...)
myArray
可以是值數組,也可以是Items
數組,也可以是單個值。
Rails足夠聰明,可以將SQL改為你的意思。 事實上,如果數組包含nil
,則SQL將是SELECT * FROM items WHERE (id IS NULL or id IN (...))
。 這明顯優於使用靜態SQL並且只能處理單個用例的原始SQL。
如果Rails沒有為您提供所需,您可以回到AREL。 例如:
class Item
scope :with_category, ->(categories) {
where( arel_table[:category].in(categories) )
}
scope :filter, ->(a, b, c) {
not_b = arel_table[:myOtherAttrib].not_eq(b)
where(:myAttrib => a, :myThirdAttrib => c).where(not_b)
}
end
Item.with_category(['small', 'large']).filter(*myVal)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.