2012-04-04 94 views
15
SELECT id, content, date 
FROM comment 
WHERE post = ? 
ORDER BY date DESC 
LIMIT ?, ? 

与PDO(我使用MAMP 2.0.5具有Apache 2.2.21,PHP高达5.3.6,和MySQL 5.5.9)准备语句这不工作,如果我改变查询与LIMIT准备语句的MySQL关键字

LIMIT 0, 10 

它的工作原理。

我看到MySQL的错误,这是以前的版本中的错误,但我不明白,如果这仍然是要修复。

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

代码:

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

你如何绑定你的参数? – alexn 2012-04-04 15:20:54

+0

解决方法是将代入“LIMIT”子句的值转换为“(int)”,并在查询中逐字指定它们。这是一个无法绕开任何东西的规避步骤,任何非有效整数表示的字符串都会导致“0”。最坏的情况下,你没有结果。 – DaveRandom 2012-04-04 15:22:00

+0

$ comments = $ db-> prepare($ query);/*其中$ db是PDO对象*/$ comments-> execute(array($ post,$ min,$ max)); – genesisxyz 2012-04-04 15:22:43

回答

34

这里的问题:

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

PDOStatement::execute()的手册页说(重点煤矿):

Parameters

input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as 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不得不说:

The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants, with these exceptions:

  • Within prepared statements, LIMIT parameters can be specified using ? placeholder markers.

  • Within stored programs, LIMIT parameters can be specified using integer-valued routine parameters or local variables.

您的选择包括:

  • 装订参数■一个接一个,所以你可以设置一个类型:

    $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驱动程序有一个bug /功能,这将使它引用的数字参数):

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

这确实是原因,但看到代码不会帮助:) – 2012-04-04 15:24:33

+3

是的,代码被高估xD – 2012-04-04 15:38:46

+0

抱歉没有发布代码,但现在一切都很清楚,谢谢! :) – genesisxyz 2012-04-04 15:46:37

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

会解决这个问题。

+0

这个工程!我必须看到这是做什么,但现在是完美的 – genesisxyz 2012-04-04 15:30:22

+8

另一个答案说明它是如何工作的。 PDO只是模拟默认准备,并且由于您默默地绑定了您的变量,而没有设置类型,所以PDO默认将它们视为字符串。 SQL中的字符串必须被引用和转义 - 因此在LIMIT子句中引用了引号,并且出现了语法错误。当使用本地准备语句时,数据库可以将事情排除在外。 – 2012-04-04 15:34:07