2014-01-09 60 views
1

我會在這裏舉兩個例子,其中$stmt = $mysqli->prepare() + $stmt->bind_param()否認可以工作,而且我也看不出爲什麼。 不工作:PHP + mySQL:Prepare,bind_param不能按我期望的那樣工作

if ($stmt = $mySQLi->prepare("DROP DATABASE ?")) { 
     $stmt->bind_param('s', $db_name); 
     $stmt->execute(); 
     $stmt->store_result(); 
} 

當前工作的解決方法:

if ($stmt = $mySQLi->prepare("DROP DATABASE $db_name")) { 
     //$stmt->bind_param('s', $db_name); 
     $stmt->execute(); 
     $stmt->store_result(); 
} 

不工作:

if ($stmt = $strSQLi->prepare("SELECT ? FROM Strings.texts WHERE keyName = ? LIMIT 1")) { 
     $stmt->bind_param('ss', strtolower($lang), strtolower("help_".$key)); 
     $stmt->execute(); 
     $stmt->store_result(); 
     $stmt->bind_result($result); 
} 

當前工作的解決方法:

if ($stmt = $strSQLi->prepare("SELECT {strtolower($lang)} FROM EVEStrings.texts WHERE keyName = ? LIMIT 1")) { 
     $stmt->bind_param('s', strtolower("help_".$key)); 
     $stmt->execute(); 
     $stmt->store_result(); 
     $stmt->bind_result($result); 
} 

任何想法,爲什麼?

+0

你不能綁定表名,表列名。您只能綁定綁定屬性值。 –

回答

4

這就是mysqli::prepare()是如何工作的。它完全寫在文檔中。

http://php.net/manual/en/mysqli.prepare.php

Note: 

的標記只在SQL語句中某些地方是合法的。例如,對於 示例,它們可以在INSERT語句 (用於指定行的列值)的VALUES()列表中,或與WHERE子句中的列 進行比較以指定比較值。

然而,他們不允許標識符(如表或列 名),在由一個 SELECT語句返回名稱的列,或指定一個二元運算的兩個操作數的選擇列表 這樣作爲=等號。後者的限制是必要的,因爲 不可能確定參數類型。它不是 允許通過比較標記與NULL嗎? IS NULL也是。通常, 參數僅在數據操縱語言(DML) 語句中合法,而不在數據定義語言(DDL)語句中合法。

這部分主要是:他們不允許標識符(如表或列名)

的綁定參數是要發送到數據庫引擎的查詢,並在runtine的想法它綁定你給出的值。如果未指定表,則引擎無法構建有效的語句,因此繼續執行查詢並且綁定參數是不可能的。

我不會建議一般使用動態表名,不管它是否安全。但是,如果你真的堅持這樣做,不要讓用戶來決定。在應用程序級別(即從數組)中決定{strtolower($lang)},而不是來自用戶輸入。

+0

我不讓用戶把任何東西放在查詢中。 $ lang是從數據庫中另一次獲取的結果。但是,謝謝你的回答!非常豐富!現在我明白了。 – user2997497

0

據我所知,從PDO(我認爲這是相同的mysqli),這是不能做到的。

bind_param and bind_value()只能綁定值,而不能綁定表或列名。

您必須手動過濾數據,也許使用白名單方法。

相關問題