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

bqucvtff  于 2023-01-16  发布在  其他
关注(0)|答案(5)|浏览(203)

这听起来像是一个愚蠢的问题,但是我注意到在很多电子商务相关项目的表格设计中,我几乎总是看到decimal(19,4)被用于货币。
为什么是4?为什么不是2?
也许我错过了一个潜在的计算问题的道路?

5w9g7ksd

5w9g7ksd1#

首先-你从其他答案中得到了一些不正确的建议。请注意以下几点(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)

注意标题下面下划线的数量--总共39条。(我把每十位改成了一个句点,以方便计数。)这正好够38位数(允许的最大值,64位CPU上的默认值)加上显示的小数点。尽管两个操作数都声明为 decimal(18,2)decimal(38,4) 数据类型执行和报告计算。(我在64位计算机上运行SQL 2012-一些细节可能会因计算机架构和操作系统而异。)
因此,很明显没有损失精度。相反,只会发生溢出,而不会损失精度。这是对十进制操作数的所有计算都作为整数算术执行的直接结果。当 decimal 类型的中间字段的类型被报告为 int 时,您偶尔会在智能上看到这种假象。
考虑上面的例子,两个操作数都是 decimal类型(18,2) 和存储为值为1、小数位数为2的整数。相乘时,乘积仍为1,但小数位数的计算方法是将小数位数相加,以创建整数值为1、小数位数为4的结果,即值为0.0001且类型为 decimal(18,4),存储为值为1、小数位数为4的整数。
再读一遍最后一段。
冲洗并重复一次。
实际上,在64位机器和操作系统上,这实际上是作为 decimal(38,4)类型存储和结转的,因为计算是在额外位空闲的CPU上进行的。
回到你的问题-世界上所有的主要货币(据我所知)只需要2位小数,但有少数需要4位,还有一些金融交易,如货币交易和债券销售,法律规定小数点后4位。数据类型微软似乎选择了可能需要的最大规模,而不是需要的正常规模。考虑到交易和公司如此之少,实际上需要大于19位的精度,这似乎是非常明智的。
如果您有:
1.对只处理主要货币的期望很高(目前只需要2位数的比例);以及
1.不期望处理法律强制要求4位数比例的交易
那么使用小数位数为2的 decimal 类型是安全的(例如 decimal(19,2)decimal(18,2) 或 * 十进制(38,2)
),而不是货币。这将使您的某些折换更加容易,并且,鉴于上述假设,不会产生任何成本。满足这些假设的典型情况是在跟踪事务处理到美分的GL或子分类帐会计系统中。但是,股票或债券交易系统将不满足**这些假设,因为在那些情况下法律强制要求4位数的比例。
区分这两种情况的一种方法是,交易是以 * 美分 * 或 * 百分比 * 报告,这只需要两位数的比例,还是以 * 基点 * 报告,这需要四位数的比例。
如果您完全不确定哪种情况适用于您的编程环境,请咨询您的财务总监或财务总监,了解您的应用程序的法律的和公认会计原则要求。(S)他将能够给予您明确的建议。

xxls0lw8

xxls0lw82#

在SQL中,19是整数的数量,4是小数的数量。
如果你只有2位小数,而你存储的可能是一些计算的结果,这会导致超过2位小数,那么“没有办法”存储这些额外的小数。
有些货币使用2位以上小数。
使用数据类型decimal,而不是money。

62lalag4

62lalag43#

像汽油价格这样的东西会使用额外的“刻度”位置,你已经看到汽油价格为每加仑1.959美元,对吗?

67up9zun

67up9zun4#

当使用decimal时,您可以根据自己的业务需求选择使用方式。
但是,当你将使用货币数据类型在SQL默认情况下,它存储与4位小数。

brjng4g3

brjng4g35#

虽然OP的问题是关于小数位数,但让我们来看看为什么19是SQL Server上常用的小数精度。
根据this文档,这是小数使用的存储空间:
| 精密度|存储字节|
| - ------|- ------|
| 1至9|五个|
| 十至十九岁|九|
| 二十至二十八岁|十三|
| 二十九至三十八|十七|
因此1精度使用的空间相当于9,10精度使用的空间相当于19。
在现实世界场景中,9对于金钱来说很容易太小,特别是如果您选择了4,那么您将处于-99999.9999和99999.9999之间。
但是19对于任何可能的情况来说都足够了,这就是SQL Server的money数据类型使用它的原因。
可以使用28或38来防止在数据库中隐藏一些错误数据的情况下转换时的错误。

相关问题