為什麼我無法將表名傳遞給準備好的 PDO 語句?
$stmt = $dbh->prepare('SELECT * FROM :table WHERE 1'); if ($stmt->execute(array(':table' => 'users'))) { var_dump($stmt->fetchAll()); }
還有其他安全的方法可以將表名插入 SQL 查詢嗎?對於安全,我的意思是我不想做
$sql = "SELECT * FROM $table WHERE 1"
P粉1387117942023-10-18 11:56:39
要了解為什麼綁定表(或列)名稱不起作用,您必須了解準備好的語句中的佔位符如何工作:它們不是簡單地替換為(適當轉義的)字串,並執行產生的SQL。相反,要求「準備」語句的 DBMS 會針對如何執行該查詢提出完整的查詢計劃,包括將使用哪些表和索引,無論您如何填寫佔位符,這些計劃和索引都是相同的。 < /p>
SELECT name FROM my_table WHERE id = :value
的計劃將與您替換:value
的內容相同,但表面上相似的SELECT name FROM :table WHERE id = :value
無法規劃,因為DBMS 不知道您實際上要從中選擇哪個表。
這也不是像PDO 這樣的抽象程式庫可以或應該解決的問題,因為它會破壞準備好的語句的2 個關鍵目的:1)允許資料庫提前決定如何執行查詢,以及多次使用同一個計劃; 2) 透過將查詢邏輯與變數輸入分開來防止安全性問題。
P粉9787424052023-10-18 09:40:36
表名和列名不能用 PDO 中的參數取代。
在這種情況下,您只需手動過濾和清理資料。實現此目的的一種方法是將簡寫參數傳遞給將動態執行查詢的函數,然後使用 switch() 語句建立用於表名稱的有效值白名單或列名。這樣,使用者輸入就不會直接進入查詢。例如:
function buildQuery( $get_var ) { switch($get_var) { case 1: $tbl = 'users'; break; } $sql = "SELECT * FROM $tbl"; }
透過不保留預設情況或使用傳回錯誤訊息的預設情況,您可以確保只使用您想要使用的值。