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->errorInfo();显示“数组”
要回显一个数组,必须使用循环。或至少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 获取多行数据 [重复]