2015-05-05 69 views
3

我想在我的Go服務器上使用MySQL的準備語句,但我不確定如何使它與未知數量的參數一起工作。一個端點允許用戶發送一個id數組,Go將從數據庫中選擇與給定id相匹配的對象。這個數組可以包含從1到20個ID的任何地方,那麼我將如何構建一個準備好的語句來處理這個問題?我見過的所有示例都需要您確切地知道查詢參數的數量。Go-MySQL-Driver:使用變量查詢參數準備好的語句

我能想到的唯一(非常不可能的)選項是準備20個不同的SELECT語句,並使用與用戶提交的id號相匹配的語句 - 但這看起來像是一個可怕的黑客攻擊。我甚至可以看到當時準備好的陳述的性能好處嗎?

我在這裏很困難,所以任何幫助將不勝感激!

+1

你可以顯示你的select語句的樣本嗎?另請參閱[這](http://stackoverflow.com/a/20275714/1078890)發佈可能會回答你的問題。 – IamNaN

回答

3

沒有RDBMS我知道能夠綁定未知數量的參數。永遠不可能將數組與未知數量的參數佔位符進行匹配。這意味着不存在結合的陣列,以查詢諸如智能方式:

SELECT xxx FROM xxx WHERE xxx in (?,...,?) 

這不是客戶機驅動程序的限制,這是根本不通過數據庫服務器的支持。

有各種解決方法。

您可以使用20?創建查詢,綁定您擁有的值,並通過NULL值完成綁定。它工作正常,因爲涉及NULL值的比較操作的特定語義。像「field =?」這樣的條件即使某些行將匹配,當參數綁定到NULL值時,它始終評估爲false。假設數組中有5個值,那麼數據庫服務器將必須處理5個提供的值以及15個NULL值。它通常足夠聰明,可以忽略空值

另一種解決方案是準備所有查詢(每個查詢具有不同數量的參數)。如果參數的最大數量有限,這只是有趣的。它適用於準備好的語句真正重要的數據庫(如Oracle)。

就MySQL而言,使用預準備語句的好處是相當有限的。請記住,準備好的語句僅在每個會話中保留,它們不會在會話中共享。如果你有很多會話,他們會記憶。另一方面,使用MySQL解析語句不涉及太多開銷(與其他數據庫系統相反)。通常,生成大量準備好的語句來涵蓋單個查詢是不值得的。

請注意,某些MySQL驅動程序提供了一個預先準備好的語句接口,但它們並未在內部使用MySQL協議的預處理語句功能(同樣,因爲通常它不值得)。

還有一些其他解決方案(如依靠臨時表),但只有參數數量很大才有意義。

+1

大量有用的信息,謝謝。我發現 - 就像你提到的那樣 - MySQL準備的語句僅限於一個特定的連接。 My Go服務器保留一個連接池併爲每個傳入的請求分配一個不同的連接,所以我不知道準備好的語句在那裏會有什麼優勢。go-mysql-driver文檔沒有指定,但是如果連接在釋放回連接池時丟失了準備好的語句,則需要在每次傳入請求時重新準備它 - 這樣可以消除任何優勢。 – hundley

相關問題