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);
$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);