pg中的数字类型如下表:
名字 | 存储尺寸 | 描述 | 范围 |
---|---|---|---|
smallint | 2字节 | 小范围整数 | -32768 to +32767 |
integer | 4字节 | 整数的典型选择 | -2147483648 to +2147483647 |
bigint | 8字节 | 大范围整数 | -9223372036854775808 to +9223372036854775807 |
decimal | 可变 | 用户指定精度,精确 | 最高小数点前131072位,以及小数点后16383位 |
numeric | 可变 | 用户指定精度,精确 | 最高小数点前131072位,以及小数点后16383位 |
real | 4字节 | 可变精度,不精确 | 6位十进制精度 |
double precision | 8字节 | 可变精度,不精确 | 15位十进制精度 |
smallserial | 2字节 | 自动增加的小整数 | 1到32767 |
serial | 4字节 | 自动增加的整数 | 1到2147483647 |
bigserial | 8字节 | 自动增长的大整数 | 1到9223372036854775807 |
如果需要以极高的精度处理数据,或者以精确的精度存储数据,那么就使用numeric类型,它没有范围限制和精确的存储,代价是存储大小和处理速度,numeric
类型上的算术运算比整数类型或者浮点数类型要慢很多。
对于定长的数字类型,类型越小,数据在磁盘和内存中占用的空间越小,同时,类型越小,可以存储的值范围越窄。而对于整数类型,较小的类型意味着较小的范围。
对于浮点类型,较小的类型表示精度较低。
”神奇“的四舍五入:
test=# SELECT 3.0::float8 * (1.0/5.0);
?column?
--------------------
0.6000000000000001
(1 row)
test=# SELECT 3.0::float8 * (1.0/5.0) <= 0.6;
?column?
----------
f
(1 row)
当系统处理货币时,对计算中的小偏差和适当舍入表示无法接受。精确的数学得出精确的结果。
test=# SELECT 3.0::numeric * (1.0/5.0);
?column?
-------------------------
0.600000000000000000000
(1 row)
所以官方文档也标明,进行精度要求高的计算时使用numeric类型。
这是因为numeric类型的舍入行为“远离零”,而double percision和float的舍入行为是“接近最近的偶数值”。
test=# SELECT x,
test-# round(x::numeric) AS num_round,
test-# round(x::double precision) AS dbl_round
test-# FROM generate_series(-3.5, 3.5, 1) as x;
x | num_round | dbl_round
------+-----------+-----------
-3.5 | -4 | -4
-2.5 | -3 | -2
-1.5 | -2 | -2
-0.5 | -1 | -0
0.5 | 1 | 0
1.5 | 2 | 2
2.5 | 3 | 2
3.5 | 4 | 4
(8 rows)