mysql CONVERT()和CAST()to integer将值增加1

mysql CONVERT()和CAST()to integer将值增加1,mysql,casting,Mysql,Casting,我试图从电话呼叫表中选择记录,其中名为call\u Rating的枚举字符串字段的值小于整数值4。Call_Rating字段只能包含值“0”、“1”、“2”、“3”、“4”、“5”。每当我使用CONVERT(Call\u Rating,UNSIGNED INTEGER)或CAST(Call\u Rating AS UNSIGNED)时,Call\u Rating字段的值将增加1。它为什么要这样做?除了从CALL()或CAST()函数中手动减去1之外,还有什么方法可以避免它? 此外,这是一个由其他

我试图从电话呼叫表中选择记录,其中名为
call\u Rating
的枚举字符串字段的值小于整数值4。
Call_Rating
字段只能包含值“0”、“1”、“2”、“3”、“4”、“5”。每当我使用
CONVERT(Call\u Rating,UNSIGNED INTEGER)
CAST(Call\u Rating AS UNSIGNED)
时,
Call\u Rating
字段的值将增加1。它为什么要这样做?除了从CALL()或CAST()函数中手动减去1之外,还有什么方法可以避免它? 此外,这是一个由其他人设置的旧数据库,目前仍在由各种系统使用,因此在不更改数据库模式的情况下解决此问题的一些方法将非常有用。

创建表 表中的数据 Select语句 预期结果 编辑2016-5-17
谢谢大家的意见。我现在明白了问题发生的原因。基本上,枚举被视为数组,CAST()/CONVERT()返回数组的索引而不是值。最好的解决方案是将ENUM更改为INT字段,但这在我的情况下是不可取的,因为DB正在实时使用,更改数据类型可能会在其他地方引起问题。出于这个原因,lserni的解决方案对我来说是最有用的。

我无法详细解释这里发生的事情,但这可能是因为您使用的是带有数值的枚举,而不是INT类型,这似乎是明智的选择

mySQL手册

我们强烈建议您不要使用数字作为枚举值,因为它不会在适当的TINYINT或SMALLINT类型上保存存储空间,而且如果您错误地引用枚举值,则很容易混淆字符串和基础数字值(可能不相同)。如果确实使用数字作为枚举值,请始终将其括在引号中。如果省略引号,则该数字被视为索引。请参阅枚举文字的处理,以了解即使是带引号的数字也可能被错误地用作数字索引值

mySQL可能使用数字索引而不是枚举值,这导致了这种奇怪


只需切换到适当的INT字段。

您应该得到
ENUM
不是字符串或整数

对我来说,这是您应该尽可能避免在DB中使用的类型

下面是一个小提琴,它可以解释为什么会发生在你身上:

正如您所看到的,当mysql将ENUM转换为int时,它返回类似于数组中保存的值(ENUM)的索引,但不是转换为int的值

但为了演示mysql power功能,您可以运行此查询以获得预期结果:

选择'CallID','Call_Rating',
ELT(强制转换('Call_Rating`为无符号)、'0'、'1'、'2'、'3'、'4'、'5')为“强制转换”,
ELT(转换('Call_Rating',带符号整数),'0','1','2','3','4','5')为'Converted'
来自“会员”电话`
有“铸造”的
或“已转换”<4;
但无论如何,这不是最好的解决办法。
我认为您最好重新设计您的db模式。

将枚举直接转换为整数会生成该枚举的索引,因为它们从1开始,第一个元素是0,变成1,以此类推

它根本没有增加1:它返回一个整数值,这个整数值似乎是正确的值加1。但它可能是其他任何东西。如果枚举数为“1”、“2”、“3”、“4”、“5”,而没有“0”,则结果看起来是正确的,即使它实际上不是

运行从CHAR传递的双转换,或在转换为CHAR后再次运行隐式转换:

SELECT CONVERT(CONVERT(Call_Rating, CHAR(1)), UNSIGNED), 0+CONVERT(Call_Rating, CHAR(1)), 0+Call_Rating, CAST(Call_Rating AS UNSIGNED) from member_calls;


+--------------------------------------------------+---------------------------------+---------------+-------------------------------+
| CONVERT(CONVERT(Call_Rating, CHAR(1)), UNSIGNED) | 0+CONVERT(Call_Rating, CHAR(1)) | 0+Call_Rating | CAST(Call_Rating AS UNSIGNED) |
+--------------------------------------------------+---------------------------------+---------------+-------------------------------+
|                                                2 |                               2 |             3 |                             3 |
+--------------------------------------------------+---------------------------------+---------------+-------------------------------+

问题可能与您使用枚举有关。有什么特别的原因让你需要用它而不是罐头吗?谢谢佩卡。我绝对同意它可能应该是一个整数字段,我可能最终不得不将其更改为整数字段,但正如我在问题中提到的,这是一个由其他人建立并与其他系统集成的旧数据库。谢谢你的回答。它最适合我的情况,因为我不一定要更改表的模式。谢谢你的建议。我可能最终会将字段更改为整数,但我宁愿避免这样做,因为其他系统正在积极使用该表。谢谢您的解释。它确实应该更改为整数,但我宁愿避免这样做,因为其他系统正在积极使用该表。
INSERT INTO `member_calls`
  (`CallID`, `Call_Rating`)
VALUES
  (510515, '4'),
  (510909, '0'),
  (538614, '3'),
  (538615, '5');
SELECT `CallID`, `Call_Rating`, CAST(`Call_Rating` AS UNSIGNED) AS 'Casted', CONVERT(`Call_Rating`, UNSIGNED INTEGER) AS 'Converted'
FROM `member_calls`
WHERE CONVERT(`Call_Rating`, SIGNED INTEGER) < 4
   OR CAST(`Call_Rating` AS UNSIGNED) < 4;
CallID  Call_Rating Casted  Converted
510909  0           1       1
CallID  Call_Rating Casted  Converted
510909  0           0       0
538614  3           3       3
SELECT `CallID`, `Call_Rating`,
  ELT(CAST(`Call_Rating` AS UNSIGNED),'0','1','2','3','4','5') AS 'Casted', 
  ELT(CONVERT(`Call_Rating`, SIGNED INTEGER),'0','1','2','3','4','5') AS 'Converted'
FROM `member_calls`
HAVING `Casted` < 4
   OR `Converted` < 4;
SELECT CONVERT(CONVERT(Call_Rating, CHAR(1)), UNSIGNED), 0+CONVERT(Call_Rating, CHAR(1)), 0+Call_Rating, CAST(Call_Rating AS UNSIGNED) from member_calls;


+--------------------------------------------------+---------------------------------+---------------+-------------------------------+
| CONVERT(CONVERT(Call_Rating, CHAR(1)), UNSIGNED) | 0+CONVERT(Call_Rating, CHAR(1)) | 0+Call_Rating | CAST(Call_Rating AS UNSIGNED) |
+--------------------------------------------------+---------------------------------+---------------+-------------------------------+
|                                                2 |                               2 |             3 |                             3 |
+--------------------------------------------------+---------------------------------+---------------+-------------------------------+