【问题标题】:LIMIT keyword on MySQL with prepared statement [duplicate]MySQL上的LIMIT关键字与准备好的语句[重复]
【发布时间】: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()

标签: php mysql prepared-statement limit


【解决方案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 子句中有引号和语法错误。而当使用原生准备好的语句时,数据库可以整理出来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多