您的位置:首页 > 产品设计 > UI/UE

将int字段改为decimal类型后出现1264 Out of range value的问题分析和处理之二

2016-12-18 22:14 549 查看
有开发同事在生产环境对某个表将int字段改成decimal(10,4)后,提示 1264 Out of range value报错,且原来值为负数,更改字段类型后,全部变为0,咨询dba这个为什么会报错,对数据有什么影响?

我收到这问题后,第一反应就是由于字段类型转换,长度不够发生了数据溢出。

于是,下面对模拟该问题进行测试:

1.建测试表

CREATE TABLE `zeng1` (

  `_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',

  `a` int(32) DEFAULT NULL,

PRIMARY KEY (`_id`)

) ENGINE=InnoDB AUTO_INCREMENT=28129 DEFAULT CHARSET=utf8 ;

2.准备测试用数据

insert into zeng1(a) values (70000);

insert into zeng1(a) values (-123);

insert into zeng1(a) values (-10);

 select * from zeng1;

+-------+-------+

| _id   | a     |

+-------+-------+

| 28129 | 70000 |

| 28130 |  -123 |

| 28131 |   -10 |

+-------+-------+

3.修改字段类型

alter table zeng1 modify column a decimal(10,4) unsigned;

Query OK, 3 rows affected, 2 warnings (0.03 sec)  

Records: 3  Duplicates: 0  Warnings: 2

4.查看warnings

(product)root@localhost [midea_gls]> show warnings;

+---------+------+--------------------------------------------+

| Level   | Code | Message                                    |

+---------+------+--------------------------------------------+

| Warning | 1264 | Out of range value for column 'a' at row 2 |

| Warning | 1264 | Out of range value for column 'a' at row 3 |

+---------+------+--------------------------------------------+

2 rows in set (0.00 sec)

上面显示第2和第3行发生了数据溢出。

5.查询类型更改后的数据

select * from zeng1;

+-------+------------+

| _id   | a          |

+-------+------------+

| 28129 | 70000.0000 |

| 28130 |     0.0000 |

| 28131 |     0.0000 |

+-------+------------+

3 rows in set (0.00 sec)

第四和第五行的a字段记录发生了溢出。应更改将字段定义为带符号的,修改字段如下:

alter table zeng1 modify column a decimal(10,4);

再把数据update:

update zeng1 set a=-123 where `_id`= 28130;

update zeng1 set a=-10 where `_id`= 28131;

查看变为正常了:

select * from zeng1;

+-------+------------+

| _id   | a          |

+-------+------------+

| 28129 | 70000.0000 |

| 28130 |  -123.0000 |

| 28131 |   -10.0000 |

+-------+------------+

3 rows in set (0.00 sec)

 decimal(10,4)的取值范围为-999999.9999到999999.9999,decimal(10,4)中的10表示全部位数为10(整数位+小数位),4表示小数位。

show warnings看到out of range表示超过了(小于最小值或大于最大值)这个值 ,建议生产环境在对一个表更改字段前,先对这个表的数据create table as select 来备份一份,若出现out of range时,

该记录的数据将全部变成0或9。

1.确保decimal(M,N)中M-N>=max(length(a)),在更改前可以查询字段a值的最大长度:

select max(length(a)) from zeng1;

2.确保有负数值的字段定义为带符号的,decmial默认为带符号,即不加 unsigned。检查字段a是否有负数值,用下面查询检查:

select count(*) from zeng1 where a like '-%',若返回值大于0,表示存在负数。

若前面在更改字段前,先对表进行了备份,表名为zeng1_bak,更改字段后,如何将数据更新回去?

select * from zeng1;

+-------+------------+

| _id   | a          |

+-------+------------+

| 28129 | 70000.0000 |

| 28130 |     0.0000 |

| 28131 |     0.0000 |

+-------+------------+

3 rows in set (0.00 sec)

select * from zeng1_bak;

+-------+-------+

| _id   | a     |

+-------+-------+

| 28129 | 70000 |

| 28130 |  -123 |

| 28131 |   -10 |

+-------+-------+

更新如下:

update zeng1 a1 set a1.a=(

select b1.a from zeng1_bak b1 where b1.`_id`=a1.`_id` and b1.`_id` in (28130,28131));

select * from zeng1;

+-------+------------+

| _id   | a          |

+-------+------------+

| 28129 | 70000.0000 |

| 28130 |  -123.0000 |

| 28131 |   -10.0000 |

+-------+------------+

3 rows in set (0.00 sec)

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐