MySQL上的LIMIT关键字与准备好的语句[重复]

Posted

技术标签:

【中文标题】MySQL上的LIMIT关键字与准备好的语句[重复]【英文标题】:LIMIT keyword on MySQL with prepared statement [duplicate] 【发布时间】:2012-04-18 08:09:18 【问题描述】:
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 的 bug 中看到这是以前版本的 bug,但我不明白这是否仍然需要修复。

如果这仍然是一个问题,有没有办法以另一种方式选择一系列行?

代码:

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

【问题讨论】:

如何绑定你的参数? 解决方法是将您替换到LIMIT 子句中的值转换为(int),并在查询中逐字指定它们。这是一个清理步骤,不能以破坏任何东西的方式规避,任何不是有效整数表示的字符串都将导致0。最坏的情况是,您没有得到任何结果。 $cmets = $db->prepare($query); /* 其中 $db 是 PDO 对象 */ $cmets->execute(array($post, $min, $max)); PHP 代码或其他任何内容没有错误, echo $db->e​​rrorInfo();显示“数组” 要回显一个数组,必须使用循环。或至少var_dump() 【参考方案1】:

问题来了:

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

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

参数

input_parameters 一个包含尽可能多元素的值数组 正在执行的 SQL 语句中的绑定参数。 所有值都是 被视为 PDO::PARAM_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

docs 有什么要说的:

LIMIT 子句可用于限制行数 由SELECT 语句返回。 LIMIT 接受一两个数字 参数,它们都必须是非负整数常量, 这些例外:

在准备好的语句中,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 子句中有引号和语法错误。而当使用本机准备好的语句时,数据库可以设法挑选出适当的类型。

【讨论】:

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

以上是关于MySQL上的LIMIT关键字与准备好的语句[重复]的主要内容,如果未能解决你的问题,请参考以下文章

我对 Java 中的准备好的语句有问题 - Mysql 8.0 [重复]

无法使用准备好的对象语句从 mysql 获取多行数据 [重复]

如何将 pdo 的准备好的语句用于 order by 和 limit 子句?

使用 PDO 准备好的语句插入致命错误 [重复]

如何查看准备好的 PDO SQL 语句 [重复]

PDO - 使用准备好的语句[重复]