如何使用 LIMIT 子句传递 PDO 参数数组?

问题描述 投票:0回答:3
$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 使用什么内部方法将参数绑定到变量。

php mysql pdo
3个回答
19
投票

如果您关闭

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?


8
投票

PDOStatement::execute
的文档中所述:

input_parameters

一个值数组,其元素数量与正在执行的 SQL 语句中的绑定参数数量相同。所有值均被视为

PDO::PARAM_STR

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

在您的例子中,MySQL 正在尝试执行具有字符串参数的

LIMIT
子句。虽然它可以尝试使用其隐式类型转换来解决这个问题,就像它在其他地方所做的那样,字符串出现在整数应该出现的位置,它根本不打扰,而是哭着跑掉了。

因此,您需要告诉 PDO 这些特定参数是整数。因为即使 PHP 也不知道它的变量是什么类型,我相信唯一的方法就是直接将它们与

PDOStatement::bindParam
PDOStatement::bindValue
绑定,就像你正在做的那样(尽管它不是 严格必须将
$data_type
参数指定为
(int)
的简单
$variable
转换,这使得 PHP 原本毫无头绪的类型系统足以使用)。

就 PDO 用于将参数绑定到变量的内部方法而言,请看一下

really_register_bound_param()
(不出所料,没有接触过 PHP,所以你会在 C 中获得很多乐趣)。

祝你好运!


0
投票

为什么要在非用户输入的情况下绑定限制值?

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

即使

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

© www.soinside.com 2019 - 2024. All rights reserved.