Php 使用prepared语句限制MySQL上的关键字

Php 使用prepared语句限制MySQL上的关键字,php,mysql,prepared-statement,limit,Php,Mysql,Prepared Statement,Limit,对于PDO(我使用的是包含Apache2.2.21、PHP升级到5.3.6和MySQL 5.5.9的MAMP 2.0.5),如果我使用 SELECT id, content, date FROM comment WHERE post = ? ORDER BY date DESC LIMIT ?, ? 它起作用了 我在MySQL的bug中看到,这是以前版本中的bug,但我不明白这是否仍然需要修复 如果这仍然是一个问题,是否有一种方法可以用另一种方法选择一系列行 代码: 问题是: $comment

对于PDO(我使用的是包含Apache2.2.21、PHP升级到5.3.6和MySQL 5.5.9的MAMP 2.0.5),如果我使用

SELECT id, content, date
FROM comment
WHERE post = ?
ORDER BY date DESC
LIMIT ?, ?
它起作用了

我在MySQL的bug中看到,这是以前版本中的bug,但我不明白这是否仍然需要修复

如果这仍然是一个问题,是否有一种方法可以用另一种方法选择一系列行

代码:

问题是:

$comments = $db->prepare($query); 
/* where $db is the PDO object */ 
$comments->execute(array($post, $min, $max)); 
该手册页的内容如下(强调我的):

参数

input_parameters
包含尽可能多元素的值数组 正在执行的SQL语句中的绑定参数所有值都是 视为PDO::PARAM_STR

因此,您的参数将作为字符串插入,因此最终的SQL代码如下所示:

$comments = $db->prepare($query); 
/* where $db is the PDO object */ 
$comments->execute(array($post, $min, $max));
这是一种特殊情况,MySQL不会强制转换为数字,但会触发解析错误:

LIMIT '0', '10'
我要说的是:

LIMIT
子句可用于约束行数 由
SELECT
语句返回<代码>限制取一个或两个数字 参数,必须都是非负整数常量,并且 这些例外情况:

  • 在准备好的语句中,
    LIMIT
    参数可以使用?占位符标记

  • 在存储程序中,可以使用整数值例程参数或局部变量指定
    LIMIT
    参数

您的选择包括:

  • 逐个绑定参数,以便可以设置类型:

    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
    
  • 不要将这些值作为参数传递:

    $comments->bindParam(1, $post, PDO::PARAM_STR);
    $comments->bindParam(2, $min, PDO::PARAM_INT);
    $comments->bindParam(3, $min, PDO::PARAM_INT);
    
  • 禁用模拟准备(MySQL驱动程序有一个错误/功能,将使其引用数值参数):


您可以声明特定属性来解决问题

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

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

如何绑定参数?解决方法是将要替换的值转换为
LIMIT
子句中的
(int)
,并在查询中逐字指定。这是一个清理步骤,不能以破坏任何内容的方式规避,任何不是有效整数表示形式的字符串都将导致
0
。最坏的情况是,您不会得到任何结果。$comments=$db->prepare($query);/*其中,$db是PDO对象*/$comments->execute(数组($post,$min,$max));PHP代码或其他任何代码中没有错误,echo$db->errorInfo();显示“数组”以回显一个必须使用循环的数组。或者至少是一个
var\u dump()
。另一个答案说明了它是如何工作的。PDO在默认情况下只是模拟准备,当您以静默方式绑定变量而不设置类型时,PDO在默认情况下将它们视为字符串。SQL中的字符串必须被引用和转义-因此在LIMIT子句中有引号,并且出现语法错误。而当使用本机准备的语句时,数据库可以进行排序。
$query = sprintf('SELECT id, content, date
    FROM comment
    WHERE post = ?
    ORDER BY date DESC
    LIMIT %d, %d', $min, $max);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );