为什么MariaDB(MySQL)会把数字字面当作字符串?

问题描述 投票:1回答:1

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

select id from table

如果我们这样做: idinteger,那么结果集就包含了整数的ID。一切都很好。然而当我们这样做时。

select 1

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

我们使用的是NodeJS(+Typescript)和TypeORM,如果这很重要的话。我记得我在PHP中也注意到了类似的事情,但是由于PHP对类型非常宽松,所以我并没有太在意。然而这次我们要把数据以JSON的形式传给外部系统,所以现在我们需要在其中添加 parseInt() 以便将字符串输入的数字转换为实际数字。

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

mysql mariadb sqldatatypes
1个回答
0
投票
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等解释语言在这里有点占了上风。


0
投票

我找到了答案。

原来MySQL将数字字面解释为64位整数。当做一个 CAST(xxx as integer) 它也将其作为64位整数处理(你不能指定为 tinyint 有)等。所以到了NodeJS的时候,它就会附带一个标签为 Int64. 然而如果你直接选择一个DB列,那么你会得到一个更合理的 Int32 或什么的。

第二部分毕竟隐藏在MySQL客户端中。默认的 mysql NPM包的作用是检查一个叫做 "连接 "的设置。bigNumberStrings 也就是 true 默认情况下,它将64位整数作为字符串保存。如果为真,则会将64位整数作为字符串保存。原因很明显--Javascript的 number 类型是一个64位浮点值,而这比64位整数要小。所以保持它为字符串,在所有情况下都能保持保真度。

另一方面,如果 bigNumberStrings=false 然后它试图将该值转换为一个 number 而只有在太大的情况下才会把它作为一串。这一点还挺好的,但又不一定一致,所以--小心处理。

我得想想我想采取哪种方案。

© www.soinside.com 2019 - 2024. All rights reserved.