2010-03-30 26 views
26

我在我的SQL的ORDER BY部分使用params時遇到了問題。它不會發出任何警告,但不會打印任何內容。如何使用準備好的PDO語句設置ORDER BY參數?

$order = 'columnName'; 
$direction = 'ASC'; 

$stmt = $db->prepare("SELECT field from table WHERE column = :my_param ORDER BY :order :direction"); 
$stmt->bindParam(':my_param', $is_live, PDO::PARAM_STR); 
$stmt->bindParam(':order', $order, PDO::PARAM_STR); 
$stmt->bindParam(':direction', $direction, PDO::PARAM_STR); 
$stmt->execute(); 

:my_param作品,但不:order:direction。它是否沒有正確內部轉義?我堅持直接在SQL中插入它?像這樣:

$order = 'columnName'; 
$direction = 'ASC'; 

$stmt = $db->prepare("SELECT * from table WHERE column = :my_param ORDER BY $order $direction"); 

是否有PDO::PARAM_COLUMN_NAME常數或一些等價物?

謝謝!

+0

另請參見[可以PHP PDO語句接受表名作爲參數?](http://stackoverflow.com/q/182287/157957) – IMSoP 2013-09-01 22:51:25

回答

12

我不認爲你可以:

  • order by子句佔位符
  • 綁定列名:您只能綁定值 - 或變量,有其價值在準備好的聲明中注入。
+3

說實話 - 它**是**可能綁定*值* (不是標識符)在'ORDER BY'子句中 – zerkms 2013-09-01 22:15:32

+1

這是部分正確的。您只能使用綁定佔位符來提供**值**。 *從來沒有可能使用綁定佔位符來提供**標識符**(如表名,列名),SQL **關鍵字**或除**值**以外的SQL語法的任何其他部分。 (基本上,一個綁定佔位符可以代替字符串字面量,日期字面量或數字字面量Period。但是正如zerkms指出的,由於可以在'ORDER BY'子句中使用文字作爲表達式的一部分,它**實際上可以在「ORDER BY」子句中使用綁定佔位符作爲表達式的一部分 – spencer7593 2015-01-16 23:55:46

38

這裏談到的問題表明,廣受喜愛的準備語句不是銀彈,嘿嘿:)

是的,你堅持直接在SQL 將它與一些注意事項,當然。 各運營商/標識必須在腳本中硬編碼,像這樣:

$orders=array("name","price","qty"); 
$key=array_search($_GET['sort'],$orders); 
$order=$orders[$key]; 
$query="SELECT * from table WHERE is_live = :is_live ORDER BY $order"; 

同爲方向。

請注意,bindParam不會轉義,因爲根本不需要轉義。它具有約束力。

+0

如果你有一個有效的字符串數組,並重新輸入你所擁有的'$ input =(string)$輸入;'to **'(string)'**你可以簡單地檢查'if(in_array($ input,$ valid_orderbys_array))'它應該基本上做同樣的事情 – 2016-07-08 20:11:57

-1

如果我不完全錯誤,帕斯卡是正確的。
PDO中唯一可能的綁定是值的綁定,就像您對':my_param'參數所做的一樣。
然而,有沒有在做危害:

$stmt = $db->prepare("SELECT field from table WHERE column = :my_param ORDER BY ".$order ." ".$direction); 
$stmt->bindParam(':my_param', $is_live, PDO::PARAM_STR); 
$stmt->execute(); 

唯一採取的將是$order$direction正確的逃逸通知,但因爲你手動設置,並沒有通過用戶輸入進行設置,我覺得你一切都準備好了。

+0

如果他不打算改變order by列和方向,那麼我認爲,將它們作爲變量是沒有任何意義的。 – Kzqai 2011-12-22 18:12:06

4

我不認爲你可以將ASC/DESC作爲準備好的聲明的一部分,但你可以列。

order 
    by 
     case :order 
      when 'colFoo' then colFoo 
      when 'colBar' then colBar 
      else colDefault 
     end 
     $direction 

由於ASC/DESC只有兩個可能的值,你可以輕鬆地驗證和硬編碼值來進行選擇。

您也可以使用ELT(FIELD(,,,,,),,,,,)函數來完成此操作,但是然後排序將始終作爲字符串完成,即使它是數字列。

0

不幸的是,我猜你不能用預先準備好的語句做出來。 這將使它不可緩存,因爲不同的列可能具有可以使用特殊排序策略進行排序的值。

使用標準轉義創建查詢並直接執行。

-1

創建if-else條件。
如果(ascCondion)然後綁定的值,但硬編碼ORDER BY列名ASC
否則
綁定的值,但硬編碼ORDER BY列名DESC

7

有可能使用準備語句在ORDER BY條款,不幸的是你需要傳遞名稱的列的順序,並且需要設置類型爲PDO_PARAM_INT

在MySQL中,你可以用這個查詢得到列的順序:

SELECT column_name, ordinal_position FROM information_schema.columns 
WHERE table_name = 'table' and table_schema = 'database' 

PHP代碼:

$order = 2; 

$stmt = $db->prepare("SELECT field from table WHERE column = :param ORDER BY :order DESC"); 
$stmt->bindParam(':param', $is_live, PDO::PARAM_STR); 
$stmt->bindParam(':order', $order, PDO::PARAM_INT); 
$stmt->execute(); 
0

這是可能。您可以在'order by'子句中使用數字而不是字段名稱。這是一個從1開始的數字,並且按查詢中字段名稱的順序排列。您可以連接ASC或DESC中的字符串。例如 「從tab1按順序選擇col1,col2,col3?」+ strDesc +「limit 10,5」。 strDesc =「ASC」/「DESC」。