如documentation of Postgres 9.0中所述,double precision
数据类型的精度为15位十进制数,存储区为8字节,则整数大于正常bigint
(8字节)存储在double precision
字段中的近似值。纠正我,如果我错了,我说大于正常bigint
,因为如果你试图将这个数字转换为bigint
,你会收到这个错误:
select 211116514527303268704::bigint;
>> ERROR: bigint out of range
当您尝试将其转换为double precision
和numeric
并比较两者时,您会发现它们是相同的:
select 211116514527303268704::numeric,
211116514527303268704::double precision,
(211116514527303268704::double precision) = (211116514527303268704::numeric);
+-----------------------+----------------------+---------+
| numeric | float8 | boolean |
+-----------------------+----------------------+---------+
| 211116514527303268704 | 2.11116514527303e+20 | t |
+-----------------------+----------------------+---------+
使用to_char()
函数返回不同的值:
select
trim(to_char((211116514527303268704::double precision),'999,999,999,999,999,999,999')),
trim(to_char((211116514527303268704::numeric),'999,999,999,999,999,999,999'));
+-----------------------------+-----------------------------+
| text | text |
+-----------------------------+-----------------------------+
| 211,116,514,527,303,270,400 | 211,116,514,527,303,268,704 |
+-----------------------------+-----------------------------+
正如您所看到的,使用to_char - 数字组合返回的值是正确的,但是to_char - double精度与double precision
中的指数部分失去一致性2.11116514527303e + 20
我不确定它是否会影响某些内容,但lc_numeric
的区域设置为'es_PY.utf8'
在这种情况下实现double precision
完全没用,或者它是保留这些双精度字段的另一种选择?这始终是首选方案,numeric
的{{1}}某些类型的广告会保留所有原始数字?
有关其他信息,我在CentOS 6 x86-64服务器上运行了PostgreSQL 9.0安装。
答案 0 :(得分:1)
原因是出于相等比较的目的,具有更高分辨率的类型被转换为较低分辨率的类型。即:在示例中,numeric
被强制转换为double precision
。
演示:
SELECT *
, num = dp AS no_cast
, num::float8 = dp AS dp_cast
, num = dp::numeric AS num_cast
FROM (
SELECT numeric '211116514527303268705' AS num
, float8 '211116514527303268705' AS dp
) t;
num | dp | no_cast | dp_cast | num_cast
----------------------+-----------------------+---------+---------+---------
211116514527303268705 | 2.11116514527303e+020 | t | t | f
float8
是double precision
的别名
请注意,对于其他计算,例如加法,结果是 更高 分辨率的类型 - 这是逻辑必需。 (无论如何,结果都是boolean
。)