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


Answers:


227

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


52
关于大小的一点:根据MSDN(msdn.microsoft.com/en-us/library/ms187746.aspx),Decimal(10,4)和Decimal(19,4)都使用9个字节的存储空间,因此可能弹簧使那额外的9位数刻度。
亚当·诺夫辛格

1
MSDN文章是有关SQL Server的,但问题是有关MySQL的。(我遇到了一些开发人员,他们认为两者相同,所以最好弄清楚。)
cja

5
使用(19,4)代替的好处是(19,2)什么?
ryvantage '16

1
我的好处是..我需要所有的表行都等于一定的金额。假设该金额为$ 10.00。随着新行的添加,每行的数量都会变化。表中是否有3行。10/3 = 3.3333333333 ...但只有两位小数,它们被存储为3.33。因此,当您将这些总和相加时,为3.33 + 3.33 + 3.33 = 9.99。我们损失了一分钱!在更大的数据集上变得更糟。将其存储在19,4并求和,然后将输出四舍五入到19,2。。–
Rick

49

您唯一需要注意的是,如果您从一个数据库迁移到另一个数据库,您可能会发现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个十进制)

不幸的是,链接现在已经死了。
MarcoAurélioDeleu

1
@MarcoAurélioDeleu-我已经更改了链接以指向Wayback Machine上的页面,因此您可以像2009
Tony

17

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

我处理了一个股价应用程序,该应用程序需要计算一百万股的价格。所报股价必须存储为7位数的准确性。


7
这是一个好点-尤其是在金融应用中,“价格”肯定并不意味着“钱”
Mike Woodhouse,2009年

17

阿萨夫的回应

取决于你有多少钱...

听起来很客气,但实际上是相关的。

直到今天,我们才遇到一个问题,即由于其中一列(GrossRate)设置为Decimal(11,4),并且我们的产品部门刚刚获得了某令人惊叹的度假胜地的客房合同,因此无法将记录插入到“费率”表中在波拉波拉岛,它的每晚售价为几百万太平洋法郎……这在十年前设计数据库架构时从未被过时。


2
这就是为什么我推荐十进制(19,4)的原因。听起来可能有些过分,但是您永远不知道何时需要在该字段中存储大量的内容。
Kibbee

2
@Kibbee:直到今天我都不会同意您的要求。(连续6年(11,4)都很好...)
Scott Ferguson

@Kibbee这听起来像是640 Kb meme :)
Nikita Bosik

13

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


如何存储6.125(6 1/8)?
PeterToTheThird 2014年

我猜他会是存储为一个整数6125.
吉米Knoot

2
有什么比这更好的DECIMAL呢?您需要非常谨慎,始终在适当的时候将几美分,米尔斯或米尔雷转换成美元。

我已经读到,即使在最新版本的MySQL中,使用INT的性能通常也比DECIMAL更快。当您需要将这些值带入PHP或某些东西并比较值时,它也更加容易。
戴恩·本迪克森

9

超级迟到,但GAAP是很好的经验法则。

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

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

资料来源:在MySQL中存储货币价值的最佳数据类型


5

DECIMAL(19,2)默认情况下,您可以对所有货币值使用类似的方法,但是如果仅存储低于$ 1,000的值,那将浪费宝贵的数据库空间。

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

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


3

这取决于数据的性质。您需要事先考虑一下。

我的情况

  • 记录货币交易的无符号十进制(13,4)
    • 存储效率高(无论如何,小数点两侧各为4个字节)1
    • 符合GAAP标准
  • 聚合的小数(19,4)无符号
    • 我们需要更多空间来处理多个数十亿笔交易
    • 半符合MS货币数据类型不会造成损害2
    • 每条记录将占用更多空间(11字节-左7字节,右4字节),但这很好,因为聚合1的记录较少
  • 汇率的小数(10,5)
    • 它们通常总共用5位数字引用,因此您可以找到类似1.2345和12.345的值,但不能找到12345.67890
    • 这是普遍的惯例,但不是统一的标准(至少就我的快速搜索知识而言)
    • 您可以使用相同的存储空间将其设置为十进制(18,9),但是数据类型限制是有价值的内置验证机制

为什么是(M,4)?

  • 有些货币可以分成几千美分
  • 有金钱等价物,如“团结报德Fermento”,“CLF”与4个显著小数表示34
  • 它符合GAAP

交易

  • 较低的精度:
    • 减少存储成本
    • 更快的计算
    • 降低计算错误风险
    • 更快的备份和还原
  • 精度更高:
    • 未来的兼容性(数量趋于增长)
    • 节省开发时间(达到限制后,您不必重建一半系统)
    • 由于存储精度不足而降低生产失败风险

兼容的极限

尽管MySQL允许您使用十进制(65,30),但是如果我们想使传输选项保持打开状态,则刻度为31,精度为30似乎是我们的限制。

最常见的RDBMS中的最大规模和精度:

            精密秤
甲骨文31 31
T-SQL 38 38
MySQL 65 30
PostgreSQL 131072 16383

6789

合理的极端

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

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

我们倾向于说“是的,当然...我不需要那个疯狂的人物”。好吧,津巴布韦人也曾经这样说。不久前。

假设您需要记录一笔100万美元的津巴布韦美元交易(今天可能不太可能,但是谁知道十年后的情况如何?)。

  1. (1百万美元)*(35 Quadrylion ZWL)=(10 ^ 6)*(35 * 10 ^ 15)= 35 * 10 ^ 21
  2. 我们需要:
    • 2位数字存储“ 35”
    • 21位数字存储零
    • 小数点右边的4位数字
  3. 这使得十进制(27,4)花费我们每个条目15个字节
  4. 我们可以在左边不加任何数字地增加一个数字-我们有15字节的小数(28,4)
  5. 现在,我们可以存储以津巴布韦美元表示的1000万美元交易,也可以避免发生另一次髋关节通货膨胀,希望这种情况不会发生

0

虽然这可能会晚一些,但是对其他人会有所帮助。根据我的经验和研究,我知道并接受十进制(19,6)。那是在使用php和mysql时。使用大量金钱和汇率时

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.