怎样在数据库中存储货币

在我们日常开发的过程中,一定会碰上和货币打交道的代码。那么这时候就会有一个问题?我们怎样在数据库中存储货币单位呢?

使用整数类型

说实话,我到现在也是使用的这种方法。以分为单位,配合 Laravel Eloquent 中的 修改器 功能,可以很轻松的实现我想要的东西。

    public function setPriceAttribute($value)
    {
        $this->attributes['price'] = intval($value * 100);
    }

    public function getPriceAttribute($value)
    {
        return $value / 100;
    }

当然,项目里的需求对精度没有那么高的要求,使用这种设计能符合我的需求。如果有更复杂的货币需求,这种设计可能就无法满足了。

使用 Monetary types 类型

注意这个方法只适合 Postgresql 数据库。有关介绍可以查看官方文档

举个栗子

[local] =# CREATE TABLE money_example (cash money);
[local] =# INSERT INTO money_example VALUES ('$99.99');
[local] =# INSERT INTO money_example VALUES (99.99);
[local] =# INSERT INTO money_example VALUES (99.98996998);

[local] =# SELECT * FROM money_example;

 cash
------------
  $99.99
  $99.99
  $99.99
(3 row)

从上面的例子可以看出数据库默认会为我们保留2位小数(四舍五入)。

看似很美好,是不是?但是有一个最大的问题是,我们只能使用一种货币单位,即要么是美元,要么是人民币等,无法混着使用。如果只用一种货币的话,那么可以考虑这种方法。

[local] =# INSERT INTO money_example VALUES ('¥99.99');
ERROR:  22P02: invalid input syntax for type money: "¥99.99"
LINE 1: INSERT INTO money_example VALUES ('¥99.99');

使用 decimal 类型

讲道理的话,这个应该是最正确的用法了。直接上栗子。

[local] =# CREATE TABLE numeric_example ( numeric_cash NUMERIC(6, 4) );
[local] =# INSERT INTO numeric_example VALUES('99.9999');
[local] =# INSERT INTO numeric_example VALUES('99.998550');
[local] =# INSERT INTO numeric_example VALUES('99.998549');
[local] =# SELECT * FROM numeric_example;
  numeric_cash
---------------
  99.9999
  99.9986
  99.9985
(3 row)

在上面的例子中我们设置了6位数的长度,并且4位是小树。当我们插入的数据长度不符合规格的时候就会抛出错误(即,小数点前面的位数大于2的时候)。

[local] =# INSERT INTO numeric_example VALUES('999.99850');
ERROR:  22003: numeric field overflow
DETAIL:  A field with precision 6, scale 4 must round to an absolute value less than 10^2.
LOCATION:  apply_typmod, numeric.c:5998

参考文章

结语

以后在开发新项目的时候,我应该会使用最后一种方法来进行货币存储。

不知道大家在开发中用的是哪种方法呢?


Practice makes perfect.

讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!