MySQL 上的 LIMIT 关键字,带有预准备语句

2022-08-30 18:14:01
SELECT id, content, date
FROM comment
WHERE post = ?
ORDER BY date DESC
LIMIT ?, ?

使用PDO(我使用的是具有Apache 2.2.21,PHP高达5.3.6和MySQL 5.5.9的MAMP 2.0.5),预处理语句这不起作用,如果我更改查询

LIMIT 0, 10

它的工作原理。

我在MySQL的错误中看到这是以前版本中的错误,但我无法理解这是否仍有待修复。

如果这仍然是一个问题,有一种方法可以以另一种方式选择行的范围?

法典:

$comments = $db->prepare($query); 
/* where $db is the PDO object */ 
$comments->execute(array($post, $min, $max)); 

答案 1

问题出在:

$comments = $db->prepare($query); 
/* where $db is the PDO object */ 
$comments->execute(array($post, $min, $max));

PDOStatement::execute() 的手册页说(强调我的):

参数

input_parameters一个值数组,其元素数与正在执行的 SQL 语句中的绑定参数数一样多。所有值都被视为 PDO::P ARAM_STR

因此,您的参数将作为字符串插入,因此最终的SQL代码如下所示:

LIMIT '0', '10'

这是MySQL不会转换为数字但触发解析错误的特殊情况:

mysql> SELECT 1 LIMIT 0, 10;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

mysql> SELECT 1 LIMIT '0', '10';
ERROR 1064 (42000): 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 ''0', '10'' at line 1

文档要说什么:

该子句可用于约束语句返回的行数。 采用一个或两个数值参数,这些参数都必须是非负整数常量,但有以下例外:LIMITSELECTLIMIT

  • 在预准备语句中,可以使用 ?占位符标记。LIMIT

  • 在存储的程序中,可以使用整数值例程参数或局部变量来指定参数。LIMIT

您的选择包括:

  • 逐个绑定参数,以便设置类型:

    $comments->bindParam(1, $post, PDO::PARAM_STR);
    $comments->bindParam(2, $min, PDO::PARAM_INT);
    $comments->bindParam(3, $min, PDO::PARAM_INT);
    
  • 不要将这些值作为参数传递:

    $query = sprintf('SELECT id, content, date
        FROM comment
        WHERE post = ?
        ORDER BY date DESC
        LIMIT %d, %d', $min, $max);
    
  • 禁用模拟准备(MySQL驱动程序有一个错误/功能,可以引用数字参数):

    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
    

答案 2

您可以声明特定属性来解决问题。

$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

另一个答案说明了它是如何工作的。默认情况下,PDO 只是模拟准备,并且由于您以静默方式绑定变量,而无需设置类型,因此默认情况下,PDO 会将其视为字符串。SQL中的字符串必须用引号和转义 - 因此您的LIMIT子句中有引号和语法错误。而当使用本机预准备语句时,数据库可以设法整理出适当的类型。


推荐