怎样在数据库中存储货币
在我们日常开发的过程中,一定会碰上和货币打交道的代码。那么这时候就会有一个问题?我们怎样在数据库中存储货币单位呢?
使用整数类型
说实话,我到现在也是使用的这种方法。以分为单位,配合 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
参考文章
结语
以后在开发新项目的时候,我应该会使用最后一种方法来进行货币存储。
不知道大家在开发中用的是哪种方法呢?
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: