不小心又中了decimal的埋伏——重新捋一下decimal的相关知识
发布时间:2020-12-12 14:56:14 所属栏目:MsSql教程 来源:网络整理
导读:大家都知道在程序语言和数据库中各种数字类型decimal,numeric,float,double,real……,有时候不小心就会出现问题,除了掌握基本的数据存储原理,还要仔细了解各个语言和产品里的细节差别,即便如此,一不小心还是有可能中了埋伏。 在SQLserver中Decimal可以
大家都知道在程序语言和数据库中各种数字类型decimal,numeric,float,double,real……,有时候不小心就会出现问题,除了掌握基本的数据存储原理,还要仔细了解各个语言和产品里的细节差别,即便如此,一不小心还是有可能中了埋伏。
在SQLserver中Decimal可以用来存储整数,也可以用来存储小数,而且精度高,所以我常常用来保存像销售类的数据相关字段。
情景再现某数据表结构如下:create table demo ( id bigint,amount decimal(18,5),--总金额 quantity decimal(18,5)--数量 )在编写一个功能其中使用了一句 select convert(decimal(18,2),amount)/convert(decimal(18,quantity) from demo where quantity>0.00 问题解决和分析执行过程中总是报“被零除的错误”,看看代码觉得没有什么问题,仔细看后才明白,原本想我要的结果只需要保留2位小数,所以执行转换后再行计算,还有一方面是quantity>0.00的判断和前面的转换不匹配造成的。尽管0.00001虽然大于0.01符合筛选条件但转化后就变成0.00了,所以才会出现上面的错误。 sql 2005中decimal的能够存储的数字范围是- 10^38 +1 到 10^38 - 1(见参考1),用科学计数法看不直观它的威力(^-^),最大正数就是4个1亿相乘以后再乘以1万减1。这是非常大的数字了。 回到正题,那么我们定义的两个字段都是decimal(18,5),表示精度为18,小数为5位, 但是要注意的是ms sql 中位数就是10进制的位数,也就是说decimal(18,5)表示-9999999999999.99999到9999999999999.99999之间的数字。这样decimal(18,5)和decimal(18,2)就有较大差别了,可以认为它们是不同的数据类型(见参考2),在两种数据数据类型之间转换,自然就可能有所损失。 解决就简单了,直接改为计算后在转化就行了。 select convert(decimal(18,2)/(amount/quantity)) from demo where quantity>0.00000 反思其实解决以上问题很简单。之所以“小题大做”,主要还是觉得对数据类型掌握还不够细,总是觉得那么数据类型,大概对就行了,差不多就行,实际上这是不对的。延伸思考,看看C#中decimal在开发中常常C#来读取数据库存储的值,就必要要定义相应的变量来存取。在C#里decimal是128位的精确数据类型,大致范围是?±1.0 × 10^-28 到 ±7.9 × 10^28,比SQL Decimal的最大范围要小一些,但是当前人类的99.999999……999999999%的应用应该是完全可以满足的(见参考3)。decimal在计算机中是如何存储? (见参考4)。 ? 参考1: decimal 和 numeric (Transact-SQL) 参考2: SQL SERVER – Difference and Explanation among DECIMAL,FLOAT and NUMERIC参考3: decimal (C# Reference) 参考4: http://topic.csdn.net/u/20090505/14/2859ab0f-579a-467b-b03a-c792bfb98bc6.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
- sql-server-2008 – SQL Server 2008的问题 – “
- sql – 在插入访问NEW后的Postgres触发器
- sql – 如何停止EF(代码优先)检查架构更改
- sql-server – 盲目添加缺失索引是否可以?
- ssms – 有没有办法为MS SQL Server Management
- centos上安装mysql并设置远程访问的操作方法
- SQL SERVER数据库开发之存储过程应用
- 数据库 – Doctrine Query Builder不使用UPDATE和
- Read Committed Snapshot和Snapshot Isolation
- mssqlserver 复制拷贝附件sql脚本(一)
热点阅读