postgresql 如何将真实的类型舍入为NUMERIC?

w9apscun  于 2022-11-23  发布在  PostgreSQL
关注(0)|答案(1)|浏览(205)

我有一个real列类型的表,其中包含示例值:

123456,12
0,12345678

和存储过程中的代码:

CREATE OR REPLACE FUNCTION test3()
  RETURNS integer AS
$BODY$
   DECLARE
      rec    RECORD;
   BEGIN

      FOR rec IN 

         SELECT
         gme.abs_km as km,
         CAST(gme.abs_km as numeric) as cast,         
         round(gme.abs_km:: numeric(16,2), 2) as round
         FROM gps_entry gme
      LOOP

         RAISE NOTICE 'Km: % , cast: % , round: %', rec.km, rec.cast, rec.round;
         INSERT INTO test (km, casting, rounding) VALUES (rec.km, rec.cast, rec.round);

      END LOOP;
      RETURN 1;      
   END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

输出如下:

2014-02-05 12:49:53 CET NOTICE:  Km: 0.12345678 , cast: 0.123457 , round: 0.12
2014-02-05 12:49:53 CET NOTICE:  Km: 123456.12 , cast: 123456 , round: 123456.00

包含NUMERIC(19,2)列的DB表:

km        casting   rounding
0.12      0.12      0.12

123456.00 123456.00 123456.00

为什么castround函数对值123456.12不起作用?

mzmfm0qo

mzmfm0qo1#

**real**是一种有损的、不精确的浮点类型。它只使用4个字节进行存储,并且可能无法精确地存储所提供的数字文字。此外,实现细节取决于您的平台。请参考手册中的“浮点类型”一章。

round()cast()都没有问题。要获得(更)精确的结果,请使用numeric

功能审核

CREATE OR REPLACE FUNCTION test3()
  RETURNS void
  LANGUAGE plpgsql AS
$func$
DECLARE
   r record;
BEGIN
   FOR r IN 
      SELECT abs_km AS km
           , cast(abs_km AS numeric) AS km_cast
           , round(abs_km::numeric, 2) AS km_round
      FROM   gps_entry
   LOOP
      RAISE NOTICE 'km: % , km_cast: % , km_round: %'
                  , r.km, r.km_cast, r.km_round;
      INSERT INTO test (km, casting, rounding)
      VALUES (r.km, r.km_cast, r.km_round);
   END LOOP;    
END
$func$;

当然,用单个多行INSERT语句替换循环会更有效。
不要引用语言名称plpgsql。它是一个标识符。
在 * 强制转换为numeric(16,2)之后 * 舍入为2个小数位数没有意义,因为numeric(16,2)已经强制舍入。可以是/或..

round(abs_km:: numeric(16,2), 2) as round
round(abs_km::numeric, 2) as round
abs_km::numeric(16,2) as round

相关问题