ChatGPT解决这个技术问题 Extra ChatGPT

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

货币值的最佳 SQL 数据类型是什么?我正在使用 MySQL,但更喜欢独立于数据库的类型。


s
shA.t

在大多数情况下,像 Decimal(19,4) 这样的东西通常效果很好。您可以调整比例和精度以适应您需要存储的数字的需要。即使在 SQL Server 中,我也倾向于不使用“money”,因为它是非标准的。


关于大小的一点:根据 MSDN (msdn.microsoft.com/en-us/library/ms187746.aspx),Decimal(10,4) 和 Decimal(19,4) 都使用 9 个字节的存储空间,所以不妨为额外的 9 位数字进行缩放。
MSDN 文章是关于 SQL Server 的,但问题是关于 MySQL 的。 (我遇到过认为两者相同的开发人员,所以最好说清楚。)
使用 (19,4) 而不是 (19,2) 有什么好处?
我的好处是……我需要我所有的表格行都等于特定数量的钱。假设金额为 10.00 美元。随着新行的添加,每行数量都会发生变化。如果表中有 3 行。 10 / 3 = 3.3333333333... 但只有 2 位小数,它们存储为 3.33。所以当你把这些加起来时,3.33 + 3.33 + 3.33 = 9.99。我们损失了一分钱!在更大的数据集上变得更糟。存储在 19,4 并将您的总数相加,然后将输出四舍五入到 19,2..
我来这里是为了考虑国际价值观,尤其是带逗号的欧元。您仍应使用小数/数字:stackoverflow.com/questions/54644222/…
T
Tony

您唯一需要注意的是,如果您从一个数据库迁移到另一个数据库,您可能会发现 DECIMAL(19,4) 和 DECIMAL(19,4) 的含义不同

(http://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-changes.html)

DBASE: 10,5 (10 integer, 5 decimal)
    MYSQL: 15,5 (15 digits, 10 integer (15-5), 5 decimal)

不幸的是,林克现在死了。
@MarcoAurélioDeleu - 我已将链接更改为指向 Wayback Machine 上的页面,因此您可以看到它在 2009 年的回顾。
L
Leah

计算出您的计算可能需要多少个小数位也很重要。

我在一个股价应用程序上工作,该应用程序需要计算一百万股的价格。报价的股价必须存储到 7 位的准确性。


这是一个很好的观点——尤其是在金融应用程序中,“价格”当然并不意味着“钱”
T
TM.

阿萨夫的回应

那要看你有多少钱了...

听起来很轻率,但实际上它是相关的。

仅在今天,我们遇到了一个问题,即未能将记录插入到我们的费率表中,因为其中一列 (GrossRate) 设置为十进制 (11,4),而我们的产品部门刚刚获得了一些令人惊叹的度假村的房间合同在波拉波拉岛,每晚售价数百万太平洋法郎……这是 10 年前设计数据库模式时从未预料到的。


这就是为什么我推荐十进制(19,4)。听起来可能有点矫枉过正,但您永远不知道何时需要在该字段中存储大量数据。
@Kibbee:直到今天我才会同意你的要求。 (6 年 (11,4) 非常好......)
如果您要处理 hyper-inflated currencies like Zimbabwe dollars,则汇率在 2009 年达到 10³⁰ 至 1 美元
d
daneb

对于会计应用程序,将值存储为整数是很常见的(有些人甚至说这是唯一的方法)。为了得到一个想法,将交易金额(假设为 100.23 美元)乘以 100、1000、10000 等,以获得所需的准确性。因此,如果您只需要存储美分并且可以安全地向上或向下舍入,只需乘以 100。在我的示例中,这将使 10023 作为要存储的整数。您将节省数据库中的空间,并且比较两个整数比比较两个浮点数要容易得多。我的 0.02 美元。


如何存储 6.125 (6 1/8)?
我猜他会将其存储为整数 6125。
这比 DECIMAL 好多少?您需要非常小心,始终在适当的时候将便士、磨坊或磨坊换算成美元。
我已经读到使用 INT 的性能通常比 DECIMAL 更快,即使在最新版本的 MySQL 中也是如此。当您需要将这些值带入 PHP 或其他东西并比较值时,它也更容易。
这是一个可行的想法,但这是一个非常过时的设计。您想要使用整数的唯一系统是那些不支持精确数字格式的系统。 25年前,这很常见。今天,几乎所有适用于业务应用程序的业务应用程序或 RDBMS 都将支持精确的数字格式,例如 SQL 的小数或 C# 的小数。我可以想象一个系统有如此大量的金融数据涌入,以至于它今天可能仍然需要整数数学,但这样的系统不会由寻找 SO 答案的人设计。
C
Community

超级迟到,但公认会计原则是一个很好的经验法则..

如果您的应用程序需要处理高达一万亿的货币价值,那么这应该可以:13,2 如果您需要遵守 GAAP(公认会计原则),则使用:13,4 通常您应该将货币价值加起来为 13,4在将输出四舍五入为 13,2 之前。

来源:Best datatype to store monetary value in MySQL


k
kshishkin

这取决于数据的性质。你需要事先考虑清楚。

我的情况

小数(13,4)无符号记录货币交易存储效率(小数点每侧4个字节)1符合GAAP

存储效率(小数点每侧 4 个字节) 1

符合公认会计原则

十进制(19,4)无符号聚合我们需要更多空间来存储多个数十亿交易的总数 半符合 MS 货币数据类型不会受到伤害 2 每条记录将占用更多空间(11 字节 - 7 左和 4 右),但这很好,因为聚合 1 的记录较少

我们需要更多空间来处理数十亿笔交易

半遵从 MS Currency 数据类型不会受到伤害 2

每条记录将占用更多空间(11 字节 - 7 左和 4 右),但这很好,因为聚合 1 的记录较少

decimal(10,5) 对于汇率,它们通常以 5 位数字引用,因此您可以找到像 1.2345 和 12.345 但不是 12345.67890 这样的值,这是普遍的约定,但不是编纂标准(至少根据我的快速搜索知识),您可以使用相同的存储使其成为十进制(18,9),但数据类型限制是有价值的内置验证机制

它们通常用 5 位数字引用,因此您可以找到像 1.2345 & 12.345 但不是 12345.67890 这样的值

这是普遍的惯例,但不是编纂的标准(至少根据我的快速搜索知识)

您可以使用相同的存储将其设为十进制 (18,9),但数据类型限制是有价值的内置验证机制

为什么是(M,4)?

有一种货币可以分裂成一千便士

有货币等价物,如“Unidad de Fermento”、“CLF”,用 4 个有效小数位表示 3,4

它符合公认会计原则

权衡

更低的精度:更少的存储成本 更快的计算 更低的计算错误风险 更快的备份和恢复

存储成本更低

更快的计算

降低计算错误风险

更快的备份和恢复

更高的精度:未来的兼容性(数量趋于增长) 节省开发时间(当达到限制时,您不必重建半个系统) 由于存储精度不足而降低生产失败的风险

未来的兼容性(数字趋于增长)

节省开发时间(当达到限制时,您不必重建半个系统)

由于存储精度不足而降低生产失败的风险

兼容极限

虽然 MySQL 允许您使用小数(65,30),但如果我们想让传输选项保持打开状态,31 表示比例和 30 表示精度似乎是我们的限制。

最常见 RDBMS 中的最大比例和精度:

Precision   Scale
Oracle      31          31
T-SQL       38          38
MySQL       65          30
PostgreSQL  131072      16383

6789

合理的极端

为什么是 (27,4)?你永远不知道系统何时需要存储津巴布韦元

2015 年 9 月 津巴布韦政府表示将以 1 美元兑 35 万亿津巴布韦元的汇率将津巴布韦元兑换成美元 5

我们倾向于说“是的,当然……我不需要那些疯狂的数字”。嗯,津巴布韦人过去也这么说。不久前。

假设您需要以津巴布韦元记录 100 万美元的交易(今天可能不太可能,但谁知道这在 10 年后会是什么样子?)。

(100 万美元) * (35 Quadrylion ZWL) = ( 10^6 ) * (35 * 10^15) = 35 * 10^21 我们需要: 2 位存储“35” 21 位存储零 4 位存储小数点的右边这使得十进制(27,4)每个条目花费我们15个字节我们可以在左边再添加一个数字而无需任何费用 - 我们有15个字节的小数(28,4)现在我们可以存储10以津巴布韦元表示的 10 万美元交易,或避免再次出现过度通货膨胀,希望这种情况不会发生


J
John Slegers

默认情况下,您可以对所有货币值使用类似 DECIMAL(19,2) 的东西,但如果您只存储低于 1,000 美元的值,那只会浪费宝贵的数据库空间。

对于大多数实现,DECIMAL(N,2) 就足够了,其中 N 的值至少是您期望存储在该字段 + 5 中的最大和的 . 之前的位数。因此,如果您不希望存储任何大于 999999.99 的值,则 DECIMAL(11,2) 应该绰绰有余(直到期望发生变化)。

如果您想符合 GAAP,您可以使用 DECIMAL(N,4),其中 N 的值至少是您希望存储在该字段中的最大总和的 . 之前的位数+ 7


p
precious

虽然这可能会迟到,但对其他人会有所帮助。根据我的经验和研究,我已经了解并接受小数(19、6)。那是在使用 php 和 mysql 时。处理大量资金和汇率时