2010-04-21 117 views
16

我想用事先準備好的聲明中傳入的參數對於ORDER BYLIMIT條款,比如:如何使用pdo的準備好的語句來排序和限制子句?

$sql = 'SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results'; 
$stmt = $dbh->prepare($sql); 
$stmt->execute(array(
    'sort' => $_GET['sort'], 
    'dir' => $_GET['dir'], 
    'start' => $_GET['start'], 
    'results' => $_GET['results'], 
    ) 
    ); 

$stmt->fetchAll(PDO::FETCH_ASSOC);回報什麼。

有人能指出我在做什麼錯事嗎?可以做到嗎?如果不是,我應該參考哪些參數可以使用的完整的子句列表?

+0

獲取值 – silent 2010-04-21 14:10:50

+0

沒有,我在其他地方填充值手動,但它仍然沒有工作。 – user198729 2010-04-21 14:12:39

+1

據我所知,你應該只綁定值,而不是列等。 – 2013-10-01 17:22:39

回答

3

您不能綁定參數來指定語言關鍵字或字段名稱 - 它必須替換文字。因此,我認爲你的極限值沒問題,但你的訂單不是。手動替換字符串中的排序和目錄將是最好的。逃避它們,但不要使用DB工具來這樣做,因爲它們不是字符串文字。基本上確保不存在特殊字符。

+0

我用':sss:xxx'替換':sort:dir'但仍然無法工作。 – user198729 2010-04-21 14:25:50

+1

這不是我的意思。它取決於你的DBMS,它看起來像。例如,對於MySQL,您不能使用關鍵字或名稱的綁定參數。在php.net上的用戶發現如下:http://www.php.net/manual/en/pdo.prepare.php#71127。但是,如果您使用的是不同的DBMS,則無視我的答案。 – 2010-04-21 21:02:30

20

使用後:

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

我得到的消息:

未捕獲的異常 'PDOException' 與 消息「SQLSTATE [42000]:語法錯誤 或訪問衝突1064您有一個您的SQL語法中有 錯誤;檢查對應於你的MySQL 服務器版本正確的語法 利用近「的 手冊」 0' ,‘10’」在1號線

所以,當您使用執行陣列,它考慮您輸入的字符串,它不是限制好主意

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results"; 
$stmt = $dbh->prepare($sql); 
$stmt->bindParam(':start', $_GET['start'], PDO::PARAM_INT); 
$stmt->bindParam(':results', $_GET['results'], PDO::PARAM_INT); 
$stmt->bindParam(':sort', $_GET['sort']); 
$stmt->bindParam(':dir', $_GET['dir']); 
$stmt->execute(); 

$data = $stmt->fetchAll(PDO::FETCH_ASSOC); 
print_r($data); 
+0

我從來沒有看到這樣的聲明參數不能在'limit'和'order'條款,使用您可以參考提供一些鏈接?是否有哪些參數可以使用的完整列表? – user198729 2010-04-21 15:06:37

+0

看起來像我錯了,只有表/列名不能被參數化。你的問題來自你的數組鍵,你忘了:(':sort'=> $ _GET ['sort'])。 – Arkh 2010-04-21 15:19:33

+0

不,':'是可選的(它仍然在增加後沒有返回':')。你可以在這裏看到這一點,如果你拉下來就夠了:http://www.php.net/manual/en/pdostatement.execute.php – user198729 2010-04-21 15:22:35

5

預處理語句讓DBMS實際執行查詢爲您提供的參數之前爲您的查詢的查詢計劃。更改ORDER BY的字段需要一個不同的查詢計劃,因爲以不同的方式排序數據會嚴重影響DBMS選擇獲取數據的方式:例如,某些索引可能在一種情況下有幫助,但在另一種情況下可能不會。因此,ORDER BY字段應該形成傳遞給prepare()方法的SQL字符串的一部分,而不是綁定到​​之前的查詢。

至於LIMIT子句,它的參數是否會影響查詢計劃並不清楚,所以這些可能會在稍後被綁定,可能取決於您的DBMS。根據this SO answer應該允許。

2

雖然這個問題還比較陳舊,但我認爲它可能還是有趣的。對我來說,它的工作後,我

  1. 使用bindParam結合PDO::PARAM_INT像建議之前
  2. 通過調用intval()

代碼的相關部分則看起來像轉換的變量的內容爲整數值這個:

$stmt->bindParam(':start', intval($_GET['start']), PDO::PARAM_INT); 
    $stmt->bindParam(':number', intval($_GET['number']), PDO::PARAM_INT); 

沒有使用intval()我也收到了錯誤語法錯誤或訪問衝突:1064您的SQL語法中有錯誤;檢查對應於你的MySQL服務器版本正確的語法使用近「」 0' ,10' 的線需要1個