18
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT :limit1, :limit2";

我想仍然像这样使用数组输入:

$stmt->execute($array);

否则我不能重用相同的方法来执行我的查询。

同时, :limit1 和 :limit2 不起作用,除非像这样放入:

$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);

我试图同时做这两个,但它没有与 bindParams 一起执行:

$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);

周围的方法是什么?

我以为我可以扩展 PDOStatement 并添加一个新方法“bindLimit”或其他东西,但我不知道 PDO 使用什么内部方法将参数绑定到变量。

4

3 回答 3

18

如果您关闭 的默认设置PDO::ATTR_EMULATE_PREPARES,那么它将起作用。我刚刚发现 mysql 默认情况下该设置处于启用状态,这意味着您实际上从未使用过准备好的语句,php 在内部为您创建动态 sql,为您引用值并替换占位符。是的,一个主要的wtf。

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare($sql);
$stmt->execute(array(5)); //works!

由于性能原因,默认情况下会模拟准备。

另见PDO MySQL:使用 PDO::ATTR_EMULATE_PREPARES 与否?

于 2012-05-03T19:24:24.313 回答
8

如文档中所述PDOStatement::execute

input_parameters

一个包含与正在执行的 SQL 语句中的绑定参数一样多的元素的值数组。所有值都被视为PDO::PARAM_STR

在大多数情况下,这完全没有被注意到,因为 MySQL 的隐式类型转换处理其余部分(但如果 MySQL 使用特别奇怪的连接字符集,它可能会导致一些不良行为,因为将数字字符串转换回它们的数值可能不会给出预期结果)。

在您的情况下,MySQL 正在尝试执行LIMIT具有字符串参数的子句。虽然它可以尝试使用其隐式类型转换来解决这个问题,就像它在其他任何地方一样,字符串出现在整数应该出现的位置,但它根本不会打扰,而是哭着跑掉。

因此,您需要告诉 PDO 这些特定参数是整数。因为即使 PHP 也不知道它的变量是什么类型,我相信唯一的方法是直接将它们绑定到PDOStatement::bindParam或者PDOStatement::bindValue像你正在做的那样(尽管将参数指定为简单的强制转换并不是绝对必要的)为PHP 的其他毫无头绪的类型系统提供了足够的支持)。$data_type(int)$variable

至于 PDO 用于将参数绑定到变量的内部方法,请看一下really_register_bound_param()(不出所料,没有暴露于 PHP,因此您将在 C 中获得很多乐趣)。

祝你好运!

于 2012-05-03T19:10:32.653 回答
0

为什么当它们不是用户输入时绑定限制值?

$start = 0;
$limit = 20;
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
    LIMIT $start, $limit";

即使$start$limit是根据用户输入确定的,例如从 a $_GET,您也可以使用 测试该值is_int()

于 2013-04-18T03:10:30.593 回答