【问题标题】:Why does MariaDB (MySQL) treat numeric literals as strings?为什么 MariaDB (MySQL) 将数字文字视为字符串?
【发布时间】:2020-09-21 06:39:46
【问题描述】:

我和我的同事今天注意到了一些奇怪的事情。如果我们这样做:

select id from table

其中idinteger,则结果集包含整数形式的ID。一切都很好。但是,当我们这样做时:

select 1

那么结果集包含字符串"1"。导致这种情况的实际情况更复杂,涉及ifnull(),但这是重现问题的最简单的事情。

如果重要的话,我们会使用 NodeJS (+Typescript) 和 TypeORM。我记得在 PHP 中也注意到了类似的东西,但是由于 PHP 对类型的要求太宽松了,所以我不太在意。然而这次我们将数据作为 JSON 传递到外部系统,所以现在我们需要添加 parseInt() 以便将字符串类型的数字转换回实际数字。

但是 - wtf?为什么会有这种行为?

【问题讨论】:

  • 为什么会有这种行为? MySQL 没有任何标记可以确定结果集列的数据类型是否必须是数字。所以它使用最常见的数据类型,即字符串一。如果您需要数字数据类型,请严格使列上下文具有确定性,例如 SELECT 1 + 0
  • @ÁlvaroGonzález 我认为 HeidiSQL 使用与 JScript 相同的 ODBC 驱动程序...
  • @Akina - 我认为数字文字 1 有点暗示数字类型...我可以理解它可能会混淆选择哪种特定类型而不是字符串...
  • @Akina 我实际上误读了这个问题。这基本上就是你所说的,MySQL 设置它认为合适的数据类型。在处理计算列时,我有时不得不使用CAST(),即使源值只是小数操作。
  • @ÁlvaroGonzález - 这很奇怪 - 即使cast(1 as integer) 变成了一个字符串......

标签: mysql mariadb sqldatatypes


【解决方案1】:

我找到了答案。

原来 MySQL 将数字文字解释为 64 位整数。在执行CAST(xxx as integer) 时,它还将其视为 64 位整数(您不能在此处指定 tinyint)等。因此,当它到达 NodeJS 时,它带有一个标签 Int64。但是,如果您直接选择数据库列,那么您会得到更合理的Int32 或其他任何内容。

第二部分毕竟隐藏在 MySQL 客户端中。默认的mysql NPM 包所做的是检查名为bigNumberStrings 的连接设置,默认为true。如果它是真的,它会将 64 位整数保存为字符串。原因很明显 - Javascript 的 number 类型是 64 位浮点值,并且小于 64 位整数。因此,将其保留为字符串可以在所有情况下保持保真度。

另一方面,如果bigNumberStrings=false 则它会尝试将值转换为number,并且仅在它太大时将其保留为字符串。这有点好,但并不总是如此 - 小心处理。

我必须考虑我要采取哪个选项。

【讨论】:

    【解决方案2】:
    WHERE id = 123      -- fine
    WHERE id = "123"    -- also fine; the string is converted to a number
    WHERE text = "123"  -- also fine (assuming `text` is VARCHAR or TEXT)
    WHERE text = 123    -- inefficient because it converts each text to numeric
    

    许多 API 将值“绑定”到查询中。他们中的许多人盲目地引用事物,而不考虑目标。请注意,上述内容表明引用始终“正常”。

    所以,我认为这就是你问的“为什么”。

    而且,正如您所说,PHP、Perl 和其他解释性语言在某种程度上占据了这里的主导地位。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-15
      • 2016-03-11
      • 2013-10-21
      • 2011-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多