money data type in postgresql

The money type in pg stores currency amounts with a fixed fractional precision; the following table:

name Storage size description range
money 8bytes Monetary amount -92233720368547758.08 to +92233720368547758.07

 

 

 

The range shown in the table assumes two decimal places.

 

Score accuracy is determined by the lc_monetary setting in the database.

postgres=# show lc_monetary;
 lc_monetary 
-------------
 en_US.UTF-8
(1 row)

postgres=# 

  

The input can be in a variety of formats, including integer and floating-point values, and typical currency formats, such as '$ 1,000.00'. The output is usually in the latter form, but depends on the locale.

 

Because the output of this data type is location-sensitive, loading currency data into a database with different lc_monetary settings may not work. To avoid problems, before restoring the dump to a new database, make sure that the value of lc_monetary is the same as or equal to the value in the dumped database.

Values ​​of numeric, int, and bigint data types can be converted to money type. Conversion from real and double precision types can be done by first converting to numeric type, for example:

postgres=# SELECT '12.34'::float8::numeric::money;
 money  
--------
 $12.34
(1 row)

postgres=# 

  

However, this is not recommended. Floating point numbers should not be used to handle money types because rounding errors may occur.

The money type can be converted to numeric without loss of precision. Conversion to other types may lose precision and must be completed in two stages:

postgres=# SELECT '52093.89'::money::numeric::float8;
  float8  
----------
 52093.89
(1 row)

postgres=# 

When the money type is divided by an integer value, the fractional part is truncated to zero. To get a rounded result, you can divide by a floating-point value, or convert the money value to a numeric value before dividing, and then convert back to the money value. (The latter is preferable to avoid the risk of losing accuracy.) When one money value is divided by another money value, the result is double precision (ie, a pure number, not a money); monetary units are divided by offset.

 

postgres=# create table money_test(m money);
CREATE TABLE
postgres=# insert into money_test values(123.456);
INSERT 0 1
postgres=# insert into money_test values(123.454);
INSERT 0 1
postgres=# show lc_monetary;
 lc_monetary 
-------------
 zh_CN.UTF-8
(1 row)
postgres=# select * from money_test;
    m     
----------
 ¥123.46
 ¥123.45
(2 rows)
postgres=# set lc_monetary='en_US.UTF-8';    
SET
postgres=# select * from money_test;
    m    
---------
 $123.46
 $123.45
(2 rows)
postgres=# select sum(m) from money_test; 
   sum   
---------
 $246.91
(1 row)

postgres=# 

  

Guess you like

Origin www.cnblogs.com/abclife/p/12679671.html