![](/img/trans.png)
[英]PDO how do I set a datetime value to NULL in a prepared statement?
[英]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.