$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT :limit1, :limit2";
我想仍然像这样使用数组输入:
$stmt->execute($array);
否则,我无法重复使用相同的方法来执行查询。
同时,:limit1 和 :limit2 不起作用,除非像这样输入:
$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);
我尝试同时执行这两项操作,但它没有与绑定参数一起执行:
$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);
有什么办法呢?
我想我可以扩展PDOStatement并添加一个新方法"bindLimit"或其他东西,但我无法弄清楚PDO使用什么内部方法将参数绑定到变量。
如果您关闭默认设置 PDO::ATTR_EMULATE_PREPARES
,那么它将起作用。我刚刚发现 mysql 默认设置是打开的,这意味着您从未实际使用预准备语句,php 在内部为您创建动态 sql,为您引用值并替换占位符。丫丫头,一个大佬。
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare($sql);
$stmt->execute(array(5)); //works!
由于性能原因,默认情况下会模拟准备工作。
另请参阅PDO MySQL:是否使用PDO::ATTR_EMULATE_PREPARES?
如PDOStatement::execute
文档中所述:
input_parameters
一个值数组,其元素数与正在执行的 SQL 语句中的绑定参数数一样多。所有值都被视为
PDO::PARAM_STR
。
在大多数情况下,这完全没有被注意到,因为MySQL的隐式类型转换处理其余部分(但如果MySQL使用特别奇怪的连接字符集,它可能会导致一些不良行为,因为将数字字符串转换回其数值可能不会给出预期的结果(。
在您的情况下,MySQL正在尝试执行具有字符串参数的LIMIT
子句。 虽然它可以尝试使用其隐式类型转换来解决这个问题,就像它在其他地方所做的那样,字符串出现在整数应该在的地方,但它根本不打扰,而是哭着跑了。
因此,您需要告诉PDO这些特定参数是整数。 由于即使是 PHP 也不知道它的变量是什么类型,我相信唯一的方法是像你正在做的那样直接将它们与 PDOStatement::bindParam
或 PDOStatement::bindValue
绑定(尽管严格来说没有必要将 $data_type
参数指定为$variable
的简单(int)
强制转换,使 PHP 原本毫无头绪的类型系统足以使用(。
至于PDO用于将参数绑定到变量的内部方法,请查看really_register_bound_param()
(不出所料,没有暴露于PHP,因此您将在C中获得很多乐趣(。
祝你好运!
值不是用户输入时,为什么要绑定限制值?
$start = 0;
$limit = 20;
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT $start, $limit";
即使$start
和$limit
是根据用户输入确定的,例如从$_GET
,您也可以使用 is_int()
测试该值。