簡體   English   中英

使用WHERE IN和Rails預處理語句語法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM