十进制(19,4)或十进制(19.2) - 我应该使用哪个?

use*_*679 13 sql t-sql sql-server sql-types

这听起来像一个愚蠢的问题,但我注意到在很多电子商务相关项目的表设计中,我几乎总是看到小数(19,4)用于货币.

为什么4规模?为什么不2?

也许我错过了一个潜在的计算问题?

Pie*_*ens 13

首先 - 您从其他答案中收到一些不正确的建议.请注意以下内容(64位架构上的64位操作系统):

declare @op1 decimal(18,2) = 0.01
       ,@op2 decimal(18,2) = 0.01;

select result = @op1 * @op2;

result
---------.---------.---------.---------
0.0001

(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

请注意标题下方的下划线数量 - 总共39个.(我每十分钟更换一次以帮助计数.)这恰好足以容纳38位数(最大允许值,64位CPU上的默认值)加上显示的小数点.尽管两个操作数都声明为十进制(18,2),但计算以十进制(38,4)数据类型执行并报告.(我在64位计算机上运行SQL 2012 - 一些细节可能因机器架构和操作系统而异.)

因此,很明显没有丢失精度.相反,只能发生溢出,而不是精度损失.这是对作为整数运算执行的十进制操作数的所有计算的直接结果.当十进制类型的中间字段的类型被报告为int时,您偶尔会看到智能的工件.

考虑上面的例子.这两个操作数都是十进制类型(18,2),并且存储为值为1的整数,其比例为2.当乘以时,乘积仍为1,但是通过添加比例来评估比例,以创建一个整数值1和小数位4的结果,其值为0.0001和十进制类型(18,4),存储为值为1且小数位数为4的整数.

再读一遍最后一段.

再冲洗并重复一次.

实际上,在64位机器和操作系统上,这实际上是以*decimal(38,4)类型存储和转发的,因为计算是在额外位空闲的CPU上完成的.

回到你的问题 - 世界上所有主要货币(我所知道的)只需要2个小数位,但有少数需要4个,并且有金融交易,如货币交易和债券销售,其中4位小数地方是法律规定的.在设计money数据类型时,Microsoft似乎选择了可能需要的最大比例,而不是所需的正常比例.鉴于很少有交易和公司实际上要求精确度大于19位,这似乎是非常明智的.

如果你有:

  1. 高期望只处理主要货币(目前只需要2位数的货币); 和
  2. 没有期望处理法律规定要求4位数字的交易

那么你就可以安全地使用类型小数与规模2(如小数(19,2)十进制(18,2)十进制(38,2) ),而不是金钱.这将简化您的部分转化,并且考虑到上述假设,不会产生任何费用.其中这些假设一个典型的例子满足是在GL或明细账会计系统跟踪交易到一分钱.但是,股票或债券交易系统不符合这些假设,因为在这种情况下法律强制要求4位数字.

区分这两种情况的一种方法是交易是以美分还是百分比报告,只需要2位数的比例,或者需要4位数的基点.

如果您完全不确定哪种情况适用于您的编程环境,请咨询您的财务总监或财务总监,了解您的申请的法律和GAAP要求.(S)他将能够给你最终的建议.

  • 令人难以置信的细节和深思熟虑.谢谢Pieter. (3认同)