如何将REAL类型四舍五入为NUMERIC?

Mac*_*iej 0 postgresql types stored-procedures plpgsql postgresql-8.3

我有real列类型带有示例值的表:

123456,12
0,12345678
Run Code Online (Sandbox Code Playgroud)

和存储过程中的代码:

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;
Run Code Online (Sandbox Code Playgroud)

输出如下:

2014-02-05 12:49:53欧洲中部通知:公里:0.12345678,演员:0.123457,回合:0.12
2014-02-05 12:49:53欧洲中部通知:公里:123456.12,演员:123456,回合:123456.00

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

km        casting   rounding
0.12      0.12      0.12

123456.00 123456.00 123456.00
Run Code Online (Sandbox Code Playgroud)

为什么castround功能无法实现价值123456.12

Erw*_*ter 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;
Run Code Online (Sandbox Code Playgroud)
  • 不要引用语言名称plpgsql。这是一个标识符。
  • 将强制转换为,舍入到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
    Run Code Online (Sandbox Code Playgroud)

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