MySQL上的LIMIT关键字,带有预处理语句

时间:2012-04-04 15:19:29

标签: php mysql prepared-statement limit

SELECT id, content, date
FROM comment
WHERE post = ?
ORDER BY date DESC
LIMIT ?, ?

使用PDO(我正在使用具有Apache 2.2.21的MAMP 2.0.5,PHP高达5.3.6和MySQL 5.5.9)准备语句这不起作用,如果我用

LIMIT 0, 10

它有效。

我在MySQL的漏洞中看到这是以前版本中的一个错误,但我无法理解这是否仍有待解决。

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

代码:

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

2 个答案:

答案 0 :(得分:38)

问题在于:

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

答案 1 :(得分:2)

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

将解决这个问题。