【问题标题】:mysql autocasting string to integermysql自动将字符串转换为整数
【发布时间】:2014-09-05 21:00:02
【问题描述】:

我的问题是一般性问题:

教义处理

$entitity->getTest()->clear();

进入这个 sql 查询:

DELETE FROM test WHERE test_id = '6'

-> test_id 是数据库中的一个整数,mysql 会自动转换该值以便它工作。 但正确的查询是:

    DELETE FROM test WHERE test_id = 6

我在这里找到了一些讨论:

stackoverflow.com/questions/21762075/mysql-automatically-cast-convert-a-string-to-a-number

code.openark.org/blog/mysql/implicit-casting-you-dont-want-to-see-around

mysql 文档说:

http://dev.mysql.com/doc/refman/5.5/en/type-conversion.html

“以下规则描述了比较操作如何进行转换”(..)在所有其他情况下,参数都作为浮点(实)数进行比较。

文档也说明了一个问题:

使用浮点数(或转换为浮点数的值)的比较是近似的,因为这样的数字是不精确的。这可能会导致结果不一致

那么,为什么学说 orm 和 dbal 也是如此呢?这不是整数表的问题吗?只有bigint?

也看这里:

http://www.cubrid.org/cubrid_implicit_type_conversion

-> 它表明这不是问题。

所以我的问题是:查询 where int_val = '1' (string) 没什么大不了的,或者这很危险。如果这很危险,那么匆忙学说是这里的设计问题吗?

【问题讨论】:

    标签: php mysql casting doctrine-orm implicit-conversion


    【解决方案1】:

    来自文档:

    • 如果一个或两个参数为NULL,则比较结果为NULL,但NULL-safe <=> 相等比较运算符除外。为了 NULL <=> NULL,结果为真。无需转换。

    • 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。

    • 如果两个参数都是整数,则将它们作为整数进行比较。

    • 如果不与数字比较,十六进制值将被视为二进制字符串。

    • 如果其中一个参数是TIMESTAMPDATETIME 列,而另一个参数是常量,则将常量转换为时间戳 在进行比较之前。这样做是为了更多 ODBC 友好。请注意,IN() 的参数不会这样做! 为安全起见,请始终使用完整的日期时间、日期或时间字符串 做比较。例如,为了在使用时达到最佳效果 BETWEEN 带有日期或时间值,使用 CAST() 显式转换 值到所需的数据类型。

    • 如果其中一个参数是十进制值,则比较取决于另一个参数。参数作为十进制值进行比较,如果 另一个参数是十进制或整数值,或作为浮点数 如果另一个参数是浮点值,则值。

    • 在所有其他情况下,将参数作为浮点(实数)数进行比较。

    您的案件属于“所有其他案件”。

    字符串将转换为 FLOAT,然后与您的 int_val 进行比较。

    如果字符串转换得很好('1''0.1''1E5' 等值),则结果值将与整数进行比较。

    如果不是(比如你传递了一个像'1235xxx' 这样的值),可能的前导数字将被转换为浮点数(0 如果没有),其余的被截断。此外,还会生成一个警告。

    在字符串中传递 id 的原因可能是您的 id 不一定必须是整数。它也可以是字符串或日期。

    可能 ORM 有一个通用代码来生成 DELETE 查询,它适用于任何数据类型。

    【讨论】:

      【解决方案2】:

      当运算符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。一些转换是隐式发生的。例如,MySQL 会根据需要自动将数字转换为字符串,反之亦然。 Reference

      这也适用于选择/插入/更新时,使用列类型作为参考。

      因此,如果您执行SELECT * FROM users WHERE balance = '1234' 并且balance 列的类型为DECIMAL (6,2),则隐含以下内容。

      mysql> SELECT CONVERT ('1234', DECIMAL (6,2));
      +---------------------------------+
      | CONVERT ('1234', DECIMAL (6,2)) |
      +---------------------------------+
      |                         1234.00 |
      +---------------------------------+
      1 row in set (0.00 sec)
      

      对于那些无法转换的值,您将始终拥有一个默认值。

      mysql> SELECT CONVERT ('test', DECIMAL (6,2));
      +---------------------------------+
      | CONVERT ('test', DECIMAL (6,2)) |
      +---------------------------------+
      |                            0.00 |
      +---------------------------------+
      1 row in set, 1 warning (0.00 sec)
      

      所以不,不涉及任何漏洞(至少在 MySQL 方面)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-21
        • 2010-12-31
        相关资源
        最近更新 更多