PostgreSQL - 从double precision字段获取所有整数数字,以便在to_char函数中使用

时间:2015-05-28 16:48:36

标签: postgresql double precision numeric to-char

documentation of Postgres 9.0中所述,double precision数据类型的精度为15位十进制数,存储区为8字节,则整数大于正常bigint(8字节)存储在double precision字段中的近似值。纠正我,如果我错了,我说大于正常bigint,因为如果你试图将这个数字转换为bigint,你会收到这个错误:

select 211116514527303268704::bigint;
>> ERROR:  bigint out of range

当您尝试将其转换为double precisionnumeric并比较两者时,您会发现它们是相同的:

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安装。

1 个答案:

答案 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

float8double precision的别名 请注意,对于其他计算,例如加法,结果是 更高 分辨率的类型 - 这是逻辑必需。 (无论如何,结果都是boolean。)