簡體   English   中英

如何使用准備好的 PDO 語句設置 ORDER BY 參數?

[英]How do I set ORDER BY params using prepared PDO statement?

我在 SQL 的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常量或一些等價物?

謝謝!

是的,您一直在將它直接插入 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";

方向也一樣。

我寫了一個白名單輔助函數用於這種情況,它大大減少了需要編寫的代碼量:

$order = white_list($order, ["name","price","qty"], "Invalid field name");
$direction = white_list($direction, ["ASC","DESC"], "Invalid ORDER BY direction");

$sql = "SELECT field from table WHERE column = ? ORDER BY $order $direction";
$stmt = $db->prepare($sql);
$stmt->execute([$is_live]);

這里的想法是檢查值並在不正確的情況下引發錯誤。

我不認為你可以:

  • order by子句中使用占位符
  • 綁定列名:您只能綁定值——或變量,並將它們的值注入到准備好的語句中。

可以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();

我不認為您可以將 ASC/DESC 作為准備好的語句的一部分,但是如果您將它們全部列在 sql 查詢中,則可以使用該列,如下所示:

// Validate between 2 possible values:
$sortDir = isset($_GET['sortDir']) && $_GET['sortDir'] === 'ASC' ? 'ASC' : 'DESC';
$sql = "
...
     order 
        by 
           case :orderByCol
               when 'email' then email
               when 'age' then age
               else surname
           end
           $sortDir
";
$stmt = $db->prepare($sql);
$stmt->bindParam(':orderByCol', $someColumn);
$stmt->execute();

由於 ASC/DESC 只有兩個可能的值,因此您可以使用 php 代碼輕松驗證和選擇它們作為硬編碼值。

您還可以為此使用 ELT(FIELD(,,,,,),,,,,) 函數,但是排序將始終作為字符串完成,即使該列是應該是數字數據類型使用數字語義/排序規則排序。

不幸的是,我猜你不能用准備好的語句來做到這一點。 這將使它無法緩存,因為不同的列可能具有可以使用特殊排序策略進行排序的值。

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

這是可能的 您可以在“order by”子句中使用數字代替字段名稱。 這是一個從 1 開始的數字,按查詢中字段名稱的順序排列。 您可以為 ASC 或 DESC 連接一個字符串。 例如“Select col1,col2,col3 from tab1 order by ?” + strDesc + “ limit 10,5”。 strDesc=" ASC" / " DESC"。

創建一個if-else條件。
If(ascCondion)然后綁定值,但硬編碼ORDER BY columnName ASC
其他
綁定值但硬代碼ORDER BY COlumnName DESC

如果我沒有完全弄錯,Pascal 是對的。
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的正確轉義,但是由於您手動設置它們並且沒有通過用戶輸入設置它們,我認為您已經設置好了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM