ChatGPT解决这个技术问题 Extra ChatGPT

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

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

deimal(10,2) 是我使用的...您可以根据预期大小调整值
相关问题是 Best Data Type for Currency ;)。

j
juergen d

由于金钱需要精确的表示,因此不要使用像 float 这样的近似数据类型。您可以使用定点数字数据类型,例如

decimal(15,2)

15 是精度(值的总长度,包括小数位)

2 是小数点后的位数

请参阅MySQL Numeric Types

当保持精确的精度很重要时使用这些类型,例如货币数据。


在这种情况下,十进制和数字数据类型之间可能有什么区别?
在 MySQL 中 decimalnumeric 是相同的。
我个人将 numeric(19,4) 用于财务记录,让您可以更好地发挥和轻松接受新请求。
我同意 YahyaE,小数越多越好。有些货币通常使用 3 个小数位,例如巴林、约旦或科威特第纳尔,因此您至少需要 3 个。四或五个更好。
@EdwinHoogerbeets 不是会计师……而是在英国经营一家小企业……我记得很久以前在某处读过,即使是英镑、美元等,货币数字也应存储为小数点后 4 位,以便某些计算可能对于某些晦涩的会计上下文,实际上使用最后 2 位小数。 Wd 需要会计师来确认/反驳。
N
NullPoiиteя

您可以使用 DECIMALNUMERIC 两者都相同

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

DECIMAL(10,2)

Good read


我使用十进制(10,2)作为我的货币价值,但是当我输入 867,000.00 之类的东西时,它被保存为 867。我做错了什么?
@codeinprogress 你的货币价值中有一个逗号......如果它以同样的方式进入数据库。 Mysql 会从逗号位置开始截断
s
shA.t

我更喜欢使用 BIGINT,并将值存储在 乘以 100,这样它就会变成整数。

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

注意:大多数情况下我们不执行货币*货币乘法,以防万一我们这样做,然后将结果除以 100 并存储,以便它返回到正确的精度。


我记得在我的计算机系统大学课程中,一位教授告诉过我类似的话。我被教导最精确的方法是通过乘以 100 并保存为整数并除以 100 以将其显示给用户来存储在便士(或美分)中。我想这对数据库系统的准确性和性能有好处。
DECIMAL有什么优势?您创造了将便士转换为美元的需求,如果您在某个时候忘记了它,您会感到很痛苦。
空间是唯一的优势,但是是的,我们在使用此功能时需要更加小心。
如果它不明显:如果您以分数美分存储钱(例如,$0.005$0.12345),请小心使用除垢方法,因为它们在乘以 100 后不会减少为整数。如果您知道精度在这些值中,很明显最好的选择是使用 DECIMAL。但是,如果您不知道精度(如我的示例中所示),那么……FLOAT 是否合适?
当使用像 JavaScript 这样使用 IEEE-754 来存储浮点数的语言时,这种方法的优势就显现出来了。本规范不保证 0.1 + 0.2 === 0.3 为真。将货币存储为整数可以确保您的应用程序不会发生这种错误。不过,这可能不是最好的解决方案。我在研究解决方案时到达了这个页面,但我还没有完成。
S
Svetoslav

这取决于您的需要。

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

如果您使用较大的值,请将 10 替换为 19


我使用十进制(10,2)作为我的货币价值,但是当我输入 867,000.00 之类的东西时,它被保存为 867。我做错了什么?
@codeinprogress 使用了错误的语言环境/小数点分隔符?
@codeinprogress 您正在使用 , 进行数字分组。不要那样做。切勿使用逗号或点进行数字分组。
d
david.ee

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

通常,在将输出四舍五入为 13.2 之前,您应该将您的货币价值加总为 13.4。


如果您要使用比特币,则需要 8 位小数,尽管大多数钱包都使用 mBTC,即 3 en.wikipedia.org/wiki/Bitcoin
不要认为这个答案是真的。 opendata.stackexchange.com/a/10348/13983 @david.ee 有来源吗?
@EvanCarroll 让我回答 david.ee。我认为这篇文章可能是来源rietta.com/blog/2012/03/03/best-data-types-for-currencymoney-in
@naXa 该链接没有引用任何支持使用 13,4 作为 GAAP 的声明的来源。您所做的只是链接到提出相同未经证实的声明的文章。
b
bizwiz

在被问到这个问题的时候,没有人考虑过比特币的价格。在 BTC 的情况下,使用 DECIMAL(15,2) 可能是不够的。如果比特币将升至 100,000 美元或更多,我们将至少需要 DECIMAL(18,9) 来支持我们的应用程序中的加密货币。

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


> 一个比特币可以分成小数点后 8 位。因此,0.00000001 BTC 是一笔交易中可以处理的最小金额。我想你的意思是 8 而不是 9?
我知道,但是 9 占用与 8 相同的磁盘空间。来自 MySQL 文档:“DECIMAL 列的值使用二进制格式存储,将九个十进制数字打包成 4 个字节”
哦,对不起,现在我明白了。谢谢。
a
antak

我们使用双。

*喘气*

为什么?

因为它可以表示任何 15 位数字,而对小数点的位置没有限制。全部只有区区 8 个字节!

所以它可以表示:

0.123456789012345

123456789012345.0

...以及介于两者之间的任何东西。

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

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

如果您尝试对 decimal 执行相同操作,则需要花费 14 个字节的 decimal(30, 15)

注意事项

当然,使用 double 并非没有注意事项。

然而,这并不是某些人倾向于指出的准确性损失。尽管 double 本身可能在内部不精确到以 10 为底的系统,但我们可以通过 将我们从数据库中提取的值 精确到它的有效小数位来使其精确.如果需要的话。 (例如,如果要输出,则需要以 10 为基数的表示。)

需要注意的是,任何时候我们使用它进行算术运算时,我们都需要在之前对结果进行规范化(通过将其四舍五入到有效的小数位):

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

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


我第一次看到这样的答案,很有趣。问:如果我将 1.41 之类的浮点数写入数据库,出于某种原因,我需要将它乘以 mysql 中的某个巨大数字,例如 1.000.000.000.000。四舍五入的结果会不会是:1.410.000.000.000?
@roelleor 为了使结果恰好为 1,410,000,000,000(逗号作为千位分隔符),假设输入为 1.410000000000(小数点后 12 位有效),但将其乘以 1,000,000,000,000(小数点后 13 位有效数字)意味着我们是使用至少 25 位有效数字。这远远超过了双倍可用的 15 个,所以在设计方面我认为它会很糟糕。
佚名

如果需要 GAAP 合规性或您需要 4 个小数位:

DECIMAL(13, 4) 支持最大值:

999,999,999.9999 美元

否则,如果 2 位小数就足够了:DECIMAL(13,2)

来源:https://rietta.com/blog/best-data-types-for-currencymoney-in/


s
shA.t

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


它与“程序员的偏好”或您“个人使用的”无关。它由需要十进制基数的问题域决定。这不是程序员可以行使自己的个人喜好的问题。
D
Deepesh

尝试使用

Decimal(19,4)

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


d
digitalstraw

在所有“正常”情况下,将钱存储为 BIGINT 乘以 100 或更多以使用更少的存储空间是没有意义的。

为了与 GAAP 保持一致,以 DECIMAL(13,4) 存储货币就足够了

MySQL手册读取它需要每9位4字节来存储DECIMAL。 https://dev.mysql.com/doc/refman/8.0/en/precision-math-decimal-characteristics.html

https://dev.mysql.com/doc/refman/8.0/en/precision-math-decimal-characteristics.html

DECIMAL(13,4) 表示 9 个数字 + 4 个小数位(小数位)=> 4 + 2 个字节 = 6 个字节

与存储 BIGINT 所需的 8 个字节相比。


a
auntyellow

乘以 10000 并存储为 BIGINT,如 Visual Basic 和 Office 中的“货币”。请参阅https://msdn.microsoft.com/en-us/library/office/gg264338.aspx