【问题标题】:PDO SQLite cannot bind NOT IN expressionPDO SQLite 不能绑定 NOT IN 表达式
【发布时间】:2017-12-05 23:22:17
【问题描述】:

代码如下:

<?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 中,这两个语句产生相同的结果。

发生了什么?这是一个错误还是记录了这个结果?

附:我已经使用https://3v4l.org/otfDj 在所有 PHP 版本上对此进行了测试,并在 5.6.0 - 5.6.30、7.0.0 - 7.2.0alpha2 中得到了相同的结果。

【问题讨论】:

    标签: php sqlite pdo


    【解决方案1】:

    这是因为execute 将传递的参数视为字符串。

    所以,你的查询变成了

    $badSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in ("2")';
    

    当然,没有等于“2”的结果。

    解决方案是绑定参数显式,如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));
    

    【讨论】:

    • 比较会不会落入In all other cases, the arguments are compared as floating-point (real) numbers.并且是一样的? (...或者这可能是 sqllite 特有的,来自 mysql,dev.mysql.com/doc/refman/5.7/en/type-conversion.html
    • 不确定这在内部是如何工作的,这个规则是否可以用于评估IN 子句。但即使两个参数都转换为浮点数,它们也可能不相等。
    猜你喜欢
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 2015-01-06
    相关资源
    最近更新 更多