在MySQL中存储货币值的最佳数据类型


279

我想在MySQL数据库中存储许多记录。它们都包含金钱价值。但是我不知道每个数字将插入多少个数字。
为此,我必须使用哪种数据类型?
VARCHARINT(或其他数字数据类型)?


13
deimal(10,2)我使用的是...您可以根据期望的大小调整值
Manse

9
相关问题是货币的最佳数据类型 ;)。
shA.t 2015年

Answers:


370

由于资金需要精确的表示,因此不要使用只近似的数据类型float。您可以将定点数字数据类型用于

decimal(15,2)
  • 15 是精度(值的总长度,包括小数位)
  • 2 是小数点后的位数

请参见MySQL数值类型

当保留精确度很重要时,例如使用货币数据,则可以使用这些类型。


3
在这种情况下,十进制和数字数据类型有什么区别?
Emilio Gort 2014年

60
在MySQL decimalnumeric都一样。
juergen d 2014年

21
我个人使用numeric(19,4)财务记录为您提供了更好的玩法,并轻松采用了新要求。
YahyaE 2015年

10
我同意YahyaE,越多的小数点越好。有些货币通常使用小数点后三位,例如巴林,约旦或科威特第纳尔,因此您至少需要3。四或五个更好。
Edwin Hoogerbeets

1
@EdwinHoogerbeets不是会计师...但是在英国经营一家小型公司...我记得很久以前读过某个货币,即使对于£,$等,货币数据也应存储为4个小数,以便进行某些计算实际上在某些晦涩的会计环境中使用最后两位小数。WD需要一位会计师来确认/驳斥。
麦克啮齿动物

88

您可以使用DECIMALNUMERIC两者都相同

DECIMAL和NUMERIC类型存储精确的数值数据值。当保留精确度很重要时,例如使用货币数据,则可以使用这些类型。在MySQL中,NUMERIC被实现为DECIMAL,因此以下有关DECIMAL的说明同样适用于NUMERIC。:MySQL

DECIMAL(10,2)

设定示例

好读


3
可能会令人困惑,但您的屏幕截图与您的答案文字(精度,比例)不匹配。
帕特里克·霍夫曼

我使用的是十进制(10,2)作为我的货币值,但是当我输入类似867,000.00的值时,它将被保存为867。我在做什么错?
codeinprogress

32

我更喜欢使用BIGINT,并将值乘以100来存储,以便它将变为整数。

例如,为了表示货币值93.49,该值应存储为9349,同时显示该值,我们可以除以100并显示。这将占用更少的存储空间。

注意:
通常,我们不执行currency * currency乘法运算,以防万一,如果将结果除以100并存储,则它会返回正确的精度。


我记得我的计算机系统大学课程中的一位教授也曾说过类似的话。有人告诉我,最精确的方法是将几分钱(或几分钱)乘以100,然后另存为整数并除以100,以显示给用户。我想这在数据库系统的准确性和性能方面有好处。
LondonAppDev 2015年

11
相比有什么优势DECIMAL?您需要将几美分转换为美元,如果您在某个时候忘记了这一点,那就会很麻烦。

1
空间是唯一的优势,但是是的,在使用此功能时,我们需要格外小心。
Dinesh PR

4
如果不是很明显:如果您以小数美分(例如,$0.005$0.12345)存储货币,请小心使用除垢方法,因为它们在乘以100后不会减少为整数。如果您知道值的精度,则很明显最好的选择是使用DECIMAL。但是,如果您不知道精度(如我的示例),那么……会FLOAT合适吗?
Quinn Comendant 2015年

1
当使用JavaScript之类的语言使用IEEE-754来存储浮点数时,这种方法的优势就来了。本规范不保证0.1 + 0.2 === 0.3是正确的。将货币存储为整数可以确定您的应用程序不会发生这种错误。但是,这可能不是最佳解决方案。我在研究解决方案时到达了此页面,但尚未完成。
加里·奥特

27

这取决于您的需要。

DECIMAL(10,2)通常使用就足够了,但是如果您需要更精确的值可以设置DECIMAL(10,4)

如果您使用较大的值,请替换1019


我使用的是十进制(10,2)作为我的货币值,但是当我输入类似867,000.00的值时,它将被保存为867。我在做什么错?
codeinprogress

2
@codeinprogress使用错误的语言环境/十进制分隔符?
DavidBalažic17年

15

如果您的应用程序需要处理高达一万亿美元的货币值,那么这应该起作用:13,2如果您需要遵守GAAP(公认会计原则),则使用:13,4

通常,在将输出舍入到13.2之前,您应该将货币值总和为13.4。


5
如果您要使用比特币,则将需要8个小数位,尽管大多数钱包都转到mBTC,即3 en.wikipedia.org/wiki/Bitcoin
Christian

不要认为这个答案是正确的。opendata.stackexchange.com/a/10348/13983 @ david.ee得到了一个来源?
埃文·卡罗尔

@EvanCarroll让我回答david.ee。我认为这篇文章可能是来源rietta.com/blog/2012/03/03/best-data-types-for-currencymoney-in
naXa

@naXa链接未引用任何支持GAAP使用13,4的说法。您所做的只是链接到提出相同的未经证实的主张的文章。
iheanyi

6

实际上,这取决于程序员的偏好。我个人使用:numeric(15,4)遵守公认会计准则(GAAP


5
它与“程序员的首选项”或您“个人使用”的内容无关。它由问题域决定,该域需要一个十进制基数。这不是程序员可以行使自己的个人喜好的问题。
洛恩侯爵,2015年

3

尝试使用

Decimal(19,4)

这通常也适用于其他所有数据库


3

我们使用double

*喘气*

为什么?

因为它可以表示任何15位数字,但对小数点在哪里没有限制。全部只有8个字节!

因此可以表示:

  • 0.123456789012345
  • 123456789012345.0

...以及介于两者之间的任何内容。

这很有用,因为我们正在处理全球货币,并且double可以存储可能遇到的各种小数位数。

单个double字段可以表示999,999,999,999,999日元(日元),9,999,999,999,999.99s(美元),甚至9,999,999.99999999s(比特币)。

如果您尝试使用 decimal,则需要decimal(30, 15)14个字节。

注意事项

当然,使用 double并非没有警告。

但是,并非如某些人所指出的那样准确性下降。即使它double本身在内部可能不适合Base 10系统,也可以通过以下方式使其精确将从数据库中拉出的值四舍五入到有效的小数位来使其精确。如果需要的话。(例如,如果要输出,并且需要以10为基数的表示形式。)

需要注意的是,每当我们对其执行算术运算时,都需要在以下步骤之前对结果进行规范化(将其舍入为有效的小数位):

  1. 对其进行比较。
  2. 将其写回数据库。

另一种警告是,与decimal(m, d)数据库将阻止程序插入数字以外的m数字不同,,此类验证不存在double。一个程序可能会插入一个用户输入的20位数的值,最终将被默默记录为一个不正确的金额。


第一次我看到这样的答案,很有趣。问:如果我向数据库中写入一个像1.41这样的浮点数,由于某种原因,我需要将它乘以mysql中的一个巨大数字,例如1.000.000.000.000。舍入后的结果将精确为:1.410.000.000.000吗?
roelleor

@roelleor为使结果精确为1,410,000,000,000(逗号作为千位分隔符),假定输入为1.410000000000(小数点后十二位),但将其乘以1,000,000,000,000(小数点后还有13个有效数字)意味着我们正在使用至少相加的25位有效数字。这远远超过了双倍可用的15,因此从设计角度来看,我认为它会非常残破。
安塔克

2

当时有人问这个问题,没人想到比特币价格。对于BTC,可能不足以使用DECIMAL(15,2)。如果比特币的价格升至100,000美元或更多,我们将至少需要DECIMAL(18,9)在我们的应用程序中支持加密货币。

DECIMAL(18,9)在MySQL中占用12个字节的空间(每9个数字4个字节)。


>比特币可以划分为8个小数位。因此,0.00000001 BTC是交易中可以处理的最小金额。我想你是说8而不是9?
危险89年

1
我知道,但是9占用的磁盘空间与8相同。从MySQL文档:“ DECIMAL列的值使用二进制格式存储,该格式将9个十进制数字打包为4个字节”
bizwiz

抱歉,现在我明白了。谢谢。
危险89年



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.