PHP 在 MySQL 查询的 LIMIT 子句中使用占位符时出现 PDO 错误

PHP PDO error when using placeholders in the LIMIT clause of a MySQL query

$sql = "SELECT sql_calc_found_rows * FROM members".
       " ORDER BY username LIMIT :startRow, :numRows";

try {
    $st = $conn->prepare($sql);
    $st->bindParam(":startRow", $startRow, PDO::PARAM_INT);
    $st->bindParam(":numRows", $numRows, PDO::PARAM_INT);
    $st->execute();
} catch (PDOException $e) {
    die("Query failed: " . $e->getMessage());
}

这里我得到错误:

Query failed: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''5'' at line 1.

LIMIT :startRow, :numRows:numRows 中有问题。

$st->bindParam$st->bindValue我都试过了,都没有用。

我解决了 it.I 键入 :numRows 占位符。

$numRows=(int)$numRows;
$sql = 'SELECT sql_calc_found_rows * FROM ' . 
    TBL_MEMBERS .'ORDER BY'.  $order .'LIMIT :startRow,:numRows';
    try {
        $st = $conn->prepare($sql);
        $st->bindValue(":startRow", $startRow, PDO::PARAM_INT);
        $st->bindValue(":numRows", $numRows, PDO::PARAM_INT);
        $st->execute();
    ...

它奏效了。我还注意到应该使用 ' 而不是 "

我认为问题出在 TBL_MEMBERS 我想这是一个视图(子选择)。 因此,如果您有产品 table 并且您想执行以下语句:

select sql_calc_found_rows * from select id, code, name, slug, info from products order by code

您将收到以下错误消息:

SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select id, code, name, slug, info from products order by code' at line 1

但是如果您将查询更改为:

select sql_calc_found_rows * from (select id, code, name, slug, info from products) v order by code

这会起作用。

总而言之, TBL_MEMBERS 是一个视图,应该放在括号中并给定别名(我的示例别名是 'v')

我建议查看 PDO 实际生成的 SQL 查询文本。您可以在 MySQL 的 general query log.

的帮助下完成此操作

最有可能的是,$startRow and/or $numRows 的形式类型是字符串,而不是整数,因此结果查询类似于 LIMIT '0', '5' (语法错误) LIMIT 0, 5(正确)。

问题是,即使使用 PDO::PARAM_INT,当参数的形式类型不是整数 (is_int returns false), PDO wraps it in quotes. So, you have to cast parameters to integers before binding them (e.g. using intval) 时:

$st->bindParam(":startRow", intval(trim($startRow)), PDO::PARAM_INT);
$st->bindParam(":numRows", intval(trim($numRows)), PDO::PARAM_INT);