货币值的最佳 SQL 数据类型是什么?我正在使用 MySQL,但更喜欢独立于数据库的类型。
9 回答
在大多数情况下,类似的东西Decimal(19,4)
通常效果很好。您可以调整比例和精度以适应您需要存储的数字的需要。即使在 SQL Server 中,我也倾向于不使用“ money
”,因为它是非标准的。
您唯一需要注意的是,如果您从一个数据库迁移到另一个数据库,您可能会发现 DECIMAL(19,4) 和 DECIMAL(19,4) 的含义不同
(http://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-changes.html)
DBASE:10,5(10 个整数,5 个十进制) MYSQL:15,5(15位,10位整数(15-5),5位小数)
计算出您的计算可能需要多少个小数位也很重要。
我在一个股价应用程序上工作,该应用程序需要计算一百万股的价格。报价的股价必须存储到 7 位的准确性。
阿萨夫的回应
那要看你有多少钱了...
听起来很轻率,但实际上它是相关的。
仅在今天,我们遇到了一个问题,即未能将记录插入到我们的费率表中,因为其中一列 (GrossRate) 设置为十进制 (11,4),而我们的产品部门刚刚获得了一些令人惊叹的度假村的房间合同在波拉波拉岛,每晚售价数百万太平洋法郎……这是 10 年前设计数据库模式时从未预料到的。
对于会计应用程序,将值存储为整数是很常见的(有些人甚至说这是唯一的方法)。为了得到一个想法,将交易金额(假设为 100.23 美元)乘以 100、1000、10000 等,以获得所需的准确性。因此,如果您只需要存储美分并且可以安全地向上或向下舍入,只需乘以 100。在我的示例中,这将使 10023 作为要存储的整数。您将节省数据库中的空间,并且比较两个整数比比较两个浮点数要容易得多。我的 0.02 美元。
超级迟到,但公认会计原则是一个很好的经验法则..
如果您的应用程序需要处理高达一万亿的货币价值,那么这应该可以:13,2 如果您需要遵守 GAAP(公认会计原则),请使用:13,4
通常,在将输出四舍五入为 13.2 之前,您应该将您的货币价值加总为 13.4。
这取决于数据的性质。你需要事先考虑清楚。
我的情况
- 用于记录货币交易的小数(13,4)无符号
- 存储效率(小数点每侧 4 个字节)1
- 符合公认会计原则
- 十进制(19,4)无符号聚合
- 十进制(10,5)汇率
- 它们通常用 5 位数字引用,因此您可以找到像 1.2345 & 12.345 但不是 12345.67890 这样的值
- 这是普遍的惯例,但不是编纂的标准(至少根据我的快速搜索知识)
- 您可以使用相同的存储将其设为十进制 (18,9),但数据类型限制是有价值的内置验证机制
为什么是(M,4)?
权衡
- 较低的精度:
- 存储成本更低
- 更快的计算
- 降低计算错误风险
- 更快的备份和恢复
- 更高的精度:
- 未来的兼容性(数字趋于增长)
- 节省开发时间(当达到限制时,您不必重建半个系统)
- 由于存储精度不足而降低生产失败的风险
兼容极限
虽然 MySQL 允许您使用小数(65,30),但如果我们想让传输选项保持打开状态,31 表示比例和 30 表示精度似乎是我们的限制。
最常见 RDBMS 中的最大比例和精度:
精密秤 甲骨文 31 31 T-SQL 38 38 MySQL 65 30 PostgreSQL 131072 16383
合理的极端
- 为什么是 (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位
- 这使得 decimal(27,4) 每个条目花费我们 15 个字节
- 我们可以免费在左边添加一位数字 - 我们有 15 个字节的小数(28,4)
- 现在我们可以存储以津巴布韦元表示的 1000 万美元交易,或者避免再次出现过度通胀,希望这种情况不会发生
您可以DECIMAL(19,2)
对所有货币值使用默认值,但如果您只存储低于 1,000 美元的值,那只会浪费宝贵的数据库空间。
对于大多数实现,DECIMAL(N,2)
就足够了,其中的值N
至少是.
您期望存储在该字段中的最大总和之前的位数+ 5
。因此,如果您不希望存储任何大于 999999.99 的值,DECIMAL(11,2)
则应该绰绰有余(直到期望发生变化)。
如果您想符合GAAP,您可以选择DECIMAL(N,4)
,其中 的值N
至少是.
您期望存储在该字段中的最大总和之前的位数+ 7
。
虽然这可能会迟到,但对其他人会有所帮助。根据我的经验和研究,我已经了解并接受小数(19、6)。那是在使用 php 和 mysql 时。处理大量资金和汇率时