【问题标题】:PDO query binding string instead of integer returns resultsPDO 查询绑定字符串而不是整数返回结果
【发布时间】:2017-08-25 14:43:31
【问题描述】:

我有一个带有自动递增 id 的表,并且只是在测试一些场景时偶然发现了一个问题,即 PDO 或 mysql 在数组中似乎将字符串转换为整数。有谁知道为什么?

如果我的查询如下:

$check = $db->prepare("SELECT * FROM tbl_test WHERE id=:id");
$check->execute(array(':id'=>1));

它检索 1 条记录 - 一切正常,但如果查询使用了一个字符串,无论是设计还是错误,如下所示:

$check = $db->prepare("SELECT * FROM tbl_test WHERE id=:id");
$check->execute(array(':id'=>'1 OR id > 0'));

它仍然检索 id=1 的记录。

肯定什么都找不到吗?我很感激我永远不应该允许第二种情况发生,但是为什么 PDO / mysql 将字符串转换为整数,它是如何做到的?

【问题讨论】:

    标签: php mysql pdo


    【解决方案1】:

    这是字符串到整数转换中的 MySQL 错误/疏忽。当给出不正确的整数文字时,它不会引发错误,而是发出警告。

    mysql> select '1'+0;
    +-------+
    | '1'+0 |
    +-------+
    |     1 |
    +-------+
    1 row in set (0,00 sec)
    
    mysql> select '1 hello world'+0;
    +-------------------+
    | '1 hello world'+0 |
    +-------------------+
    |                 1 |
    +-------------------+
    1 row in set, 1 warning (0,00 sec)
    
    mysql> show warnings;
    +---------+------+---------------------------------------------------+
    | Level   | Code | Message                                           |
    +---------+------+---------------------------------------------------+
    | Warning | 1292 | Truncated incorrect DOUBLE value: '1 hello world' |
    +---------+------+---------------------------------------------------+
    1 row in set (0,00 sec)
    

    【讨论】:

    • 非常感谢。有趣的是,即使我绑定一个参数并使用 'PDO::PARAM_INT' 也没有任何区别 - 只是发出警告。
    • 当您尝试将字符串与PDO::PARAM_INT 绑定时,我很惊讶地发现bindParam 不会抛出异常......似乎它遵循PHP 的一般字符串> Int 转换规则。
    • ...实际上bindParam 甚至没有像我想的那样做:stackoverflow.com/questions/833510/…(在被指出时做了一些进一步的挖掘并删除了我的错误答案)@user2875878
    • Weeell... 它是 PHP。任何期望 PHP 对类型做正确事情的人都在吸毒......
    • @peufeu 但是,在这种精确情况下,它的行为与 MySQL 完全一样 (demo),而且它并不比 JavaScript (demo) 更疯狂。
    【解决方案2】:

    无论好坏,这就是 MySQL 的设计行为方式:

    mysql> SELECT CASE
        -> WHEN 123='123 pink elephants' THEN 'Equal'
        -> ELSE 'Different' END
        -> AS 'How are they?';
    +---------------+
    | How are they? |
    +---------------+
    | Equal         |
    +---------------+
    1 row in set, 1 warning (0.00 sec)
    

    如您所见,它会触发警告:

    mysql> SHOW WARNINGS;
    +---------+------+--------------------------------------------------------+
    | Level   | Code | Message                                                |
    +---------+------+--------------------------------------------------------+
    | Warning | 1292 | Truncated incorrect DOUBLE value: '123 pink elephants' |
    +---------+------+--------------------------------------------------------+
    1 row in set (0.00 sec)
    

    【讨论】:

      【解决方案3】:

      这是因为 execute 创建类似:SELECT * FROM tbl_test WHERE id='1 OR id > 0'

      $check = $db->prepare("SELECT * FROM tbl_test WHERE id=:id OR id>:id2");
      $check->execute(array(':id'=>'1', ':id2' => 0));
      

      或者只是

      $check = $db->prepare("SELECT * FROM tbl_test WHERE id>:id");
      $check->execute(array(':id'=>'0'));
      

      【讨论】:

        【解决方案4】:

        使用准备好的语句和占位符,数据库知道期望一个适合列类型的值。我希望它会看到您的数字 id 列并将“1 或 id > 0”转换为一个数字 - 所以您只需得到 1。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-11-16
          • 2023-04-10
          • 2023-04-08
          • 1970-01-01
          • 2015-01-29
          • 2017-05-18
          • 2016-09-03
          相关资源
          最近更新 更多