以下是代码:
<?php
$dbh = new \PDO('sqlite:');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$goodSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in (2)';
echo json_encode($dbh->query($goodSql)->fetchAll(PDO::FETCH_NUM));
$badSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in (?)';
$binds = ['2'];
$statement = $dbh->prepare($badSql);
$statement->execute($binds);
echo json_encode($statement->fetchAll(PDO::FETCH_NUM));
?>
第一个语句成功地从结果中排除了2
。排除由内联SQL条件NOT IN (2)
指定。
第二个语句无法从结果中排除2
。排除是由条件2
中参数NOT IN (?)
的PDO绑定指定的。
在PDO / MySQL中,这两个语句产生相同的结果。
发生了什么事?这是一个错误还是记录了这个结果?
P.S。我在使用https://3v4l.org/otfDj的所有PHP版本上测试了这个,并且得到了与5.6.0 - 5.6.30,7.0.0 - 7.2.0alpha2相同的结果。
答案 0 :(得分:3)
这是因为execute
将传递的参数视为字符串。
因此,您的查询变为
$badSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in ("2")';
当然,没有结果等于&#34; 2&#34;。
解决方案是绑定params explicilty,如int
:
$badSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in (?)';
$binds = ['2'];
$statement = $dbh->prepare($badSql);
$statement->bindValue(1, '2', PDO::PARAM_INT); // this is it
$statement->execute();
echo json_encode($statement->fetchAll(PDO::FETCH_NUM));