如何使用准备好的PDO语句设置ORDER BY参数?

Mar*_*orn 33 php mysql pdo

我在ORDER BYSQL 的部分使用params时遇到问题.它不会发出任何警告,但不打印任何内容.

$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();
Run Code Online (Sandbox Code Playgroud)

:my_param作品,但没有:order:direction.是不是在内部正确转义?我是不是直接插入SQL?像这样:

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

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

PDO::PARAM_COLUMN_NAME常数还是等价?

谢谢!

You*_*nse 51

这里出现的问题表明,广受喜爱的预备声明不是银弹,呵呵:)

是的,当然,您可能会直接将其插入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";
Run Code Online (Sandbox Code Playgroud)

方向相同.

请注意,bindParam不会转义,因为根本不需要转义.它有约束力.


Pas*_*TIN 12

我认为你不能:

  • order by子句中使用占位符
  • 绑定列名:您只能绑定值 - 或变量,并将其值注入预准备语句中.

  • 说实话 - ****可以在`ORDER BY`子句中绑定*值*(不是标识符) (3认同)
  • 这是部分正确的。您只能使用绑定占位符来提供 **values** 。*永远*不可能使用绑定占位符来提供**标识符**(如表名、列名)、SQL **关键字**或除**值**以外的任何其他SQL语法部分。(基本上,绑定占位符可以代替字符串文字、日期文字或数字文字。句点。但正如 zerkms 指出的那样,因为可以使用文字作为 `ORDER BY` 子句中表达式的一部分,它**是**实际上可以使用绑定占位符作为`ORDER BY`子句中表达式的一部分。 (2认同)

rra*_*ray 10

可能ORDER BY子句中使用预处理语句,遗憾的是您需要传递名称列的命令,并且需要设置PDO_PARAM_INT类型.

在MySQL中,您可以使用此查询获取列的顺序:

SELECT column_name, ordinal_position FROM information_schema.columns 
WHERE table_name = 'table' and table_schema = 'database'
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

  • 聪明的解决方法。不过,就我个人而言,我认为首先必须找出列号实在是太多了。 (2认同)

goa*_*oat 5

我不认为您可以在准备好的语句中获得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();
Run Code Online (Sandbox Code Playgroud)

由于ASC / DESC只是两个可能的值,因此您可以轻松地使用php代码验证并在其中选择作为硬编码值。

您也可以为此使用ELT(FIELD(,,,,,,,,,,))函数,但是即使列是应该为使用数字语义/排序规则排序。