1

我有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 通知:公里:0.12345678,投:0.123457,回合:0.12
2014-02-05 12:49:53 CET 通知:公里:123456.12,演员:123456,回合:123456.00

带有列的数据库表NUMERIC(19,2)

km        casting   rounding
0.12      0.12      0.12

123456.00 123456.00 123456.00

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

4

1 回答 1

5

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

round()或都没有错cast()。要获得准确的结果,您必须先使用numeric

功能审核

CREATE OR REPLACE FUNCTION test3()
  RETURNS void 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$ LANGUAGE plpgsql;
  • 不要引用语言名称plpgsql。这是一个标识符。
  • 在强制转换为 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

最后,您需要升级到当前版本。Postgres 8.3 已达到 EOL 且不受支持。

于 2014-02-05T19:40:50.867 回答