我的MySQL
db上有一个名为membertable
的表。该表由两个字段memberid
和membername
组成。 memberid
字段的类型为integer
,并使用从2001
开始的auto_increment函数。 membername
表的类型为varchar
。
membertable
有两条记录,其顺序与上述相同。记录如下:
memberid:2001 会员名称:约翰史密斯
memberid:2002 会员名:将史密斯
当我针对SELECT
字段运行memberid
语句时,我发现了一些奇怪的东西。运行以下语句:
SELECT * FROM `membertable` WHERE `memberid` = '2001somecharacter'
它返回了第一个数据。
为什么会这样? memberid
= 2001somecharacter
没有记录。看起来MySQL只搜索前4个字符(2001),当它找到相关数据时,就是上面返回的数据,它会拒绝剩下的字符。
怎么会发生这种情况?有没有办法关闭这种行为?
-
membertable
使用innodb
引擎
答案 0 :(得分:0)
这是因为mysql试图将“2001somecharacter”转换为返回2001的数字。
由于您要将数字与字符串进行比较,因此您应该使用
SELECT * FROM `membertable` WHERE CONVERT(`memberid`,CHAR) = '2001somecharacter';
避免这种行为。
要正确地执行,不要将您的搜索变量放在引号中,以便它必须是一个数字,否则它会因为语法错误而爆炸,然后在前端确保它是一个数字,然后传入查询
答案 1 :(得分:0)
您的发现是一种被驱逐的MySQL行为。 MySQL将varchar转换为从头开始的整数。只要存在可以轻松转换的数字字符,它们就会被包含在转换过程中。如果有一个字母,转换将停止返回到目前为止读取的数字字符串的整数值...
Here在MySQL文档站点上对此行为进行了一些描述。不幸的是,它没有直接在文中提及,但有一个例子可以准确地显示这种行为。
答案 2 :(得分:0)
在数值上下文中计算时,MySQL非常自由地将字符串值转换为数值。
作为演示,添加0会导致在数字上下文中计算字符串:
SELECT '2001foo' + 0 --> 2001
, '01.2-3E' + 0 --> 1.2
, 'abc567g' + 0 --> 0
当在数字上下文中计算字符串时,MySQL会逐个字符地读取字符串,直到它遇到一个字符,其中字符串不能再被解释为数字值,或者直到它到达字符串的末尾。< / p>
我不知道如何关闭&#34;&#34;或禁用此行为。 (可能有一个sql_mode设置可以更改此行为,但可能该更改将影响正在工作的其他SQL语句,如果进行了更改,则可能会停止工作。
通常,这种参数检查是在应用程序中完成的。
但是如果你需要在SELECT语句中执行此操作,则会将一个选项转换/转换为字符串,然后进行比较。
但这会产生一些重大的性能影响。如果我们对WHERE子句中的条件中的列进行强制转换或转换(或任何函数),MySQL将无法对合适的索引使用范围扫描操作。我们强制MySQL在表中的每个行执行强制转换/转换操作,并将结果与文字进行比较。
所以,这不是最好的模式。
如果我需要在SQL语句中执行类似的检查,我会这样做:
WHERE t.memberid = '2001foo' + 0
AND CAST('2001foo' + 0 AS CHAR) = '2001foo'
第一行与当前查询做同样的事情。这可以利用合适的指数。
第二个条件是将相同的值转换为数字,然后将其转换回字符,然后将结果与原始值进行比较。使用此处显示的值,它将评估为FALSE,并且查询将不返回任何行。
如果字符串值具有前导空格,那么这也不会返回一行,&#39; 2001&#39 ;.第二个条件是评估为FALSE。
答案 3 :(得分:0)
将INT
与'string'进行比较时,字符串将转换为数字。
将字符串转换为数字可以使用尽可能多的前导字符,但仍然是数字。因此'2001character'
被视为数字2001
。
如果您想要member_id
中的非数字字符,请将其设为VARCHAR
如果您只想要数字ID,请拒绝'200.1character'