关于mysql存储过程中传decimal值会自动四舍五入的这个坑

容我说几句题外话:我的工作日常是用微软系的,SQL SERVICE 存储过程很强大,我也很习惯很喜欢用存储过程。和MySQL结缘,是在五年前,因为一些原因,公司要求用开源免费的数据库。很多时候,用mysql的程序员是不会去用存储过程的,除了调试麻烦外,还有其它各种小问题。说实在的,MySQL这些年发展很快,但和SQL SERVICE的差距还是很大的。好了,不说废话了,言归正转。

 

首先,描述我的场景

假如,我们有一张订单表 t_order 结构如下:

字段名 类型 描述
id int(11) <auto_increment> id,自增,主键
orderNo varchar(20) 订单编号,唯一约束
price decimal(10,2) 价格

 

我们不要去纠结这张表的完整性,也不要去纠结为什么价格不直接用int表示单位为分的额。现在假如,我们写一个生成订单存储过程:

CREATE  PROCEDURE `p_order_create`(IN `_OrderNo` tinytext,IN `_Price` decimal,OUT `_res` int)


BEGIN
   /*
          用途:生成订单

          参数:
          IN `_OrderNo` tinytext,
          IN `_Price` decimal
          _res : 执行结果,0表示失败,成功时返回订单的id
   
   */

  
  INSERT INTO t_order
  (`orderNo`,`price`)
  VALUES 
  (_OrderNo,_Price);

  select @@Identity INTO _res;

END;

当我们在调用时,给价格传入的是一个小数时,如:

CALL p_order_create('abc',5.8,@res)

 

我们会发现,存入表 t_order中的这一条数据,price是6,四舍五入了。。。。,说实在的,之前我一直都是用int来表示钱的最小单位(当前业务的最小单位),比如RMB一元,我就存100的整型,所以一直没有留意到MySQL这个坑。当然了,这个坑的解决方案也很简单,我们只要给decimal在申明时指定它的精度,比如decimal(10,2),即存储过程可以改为:

CREATE  PROCEDURE `p_order_create`(IN `_OrderNo` tinytext,IN `_Price` decimal(10,2),OUT `_res` int)


BEGIN
   /*
          用途:生成订单

          参数:
          IN `_OrderNo` tinytext,
          IN `_Price` decimal
          _res : 执行结果,0表示失败,成功时返回订单的id
   
   */

  
  INSERT INTO t_order
  (`orderNo`,`price`)
  VALUES 
  (_OrderNo,_Price);

  select @@Identity INTO _res;

END;

 

 

这个坑,记录在这里,也是对自己的一个提醒吧!

 

posted @ 2018-03-08 17:44  MrBug  阅读(1949)  评论(0编辑  收藏  举报

人生就是一场战斗,唯有披荆斩棘,勇往直前!