【问题标题】:How to round REAL type to NUMERIC?如何将 REAL 类型四舍五入为 NUMERIC?
【发布时间】:2014-03-01 20:25:01
【问题描述】:

我有带有示例值的 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

【问题讨论】:

  • 要格式化数字以显示给用户,请使用to_char
  • 实际上我想将这些值插入到带有数字(19,2)列的数据库表中,我已经更新了相关代码
  • 问题似乎与超过 6 位的数字有关,因为这些数字的转换和舍入工作:1.23 1234.12, 123.456

标签: postgresql stored-procedures types plpgsql postgresql-8.3


【解决方案1】:

real 是一种有损、不精确的浮点类型。它仅使用 4 个字节进行存储,并且无法精确存储所呈现的数字文字。此外,实施细节取决于您的平台。考虑the chapter "Floating-Point Types" in the manual.

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。这是一个标识符。
  • 在转换为numeric(16,2) 之后, 舍入到 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 has reached EOL and is unsupported.

【讨论】:

    猜你喜欢
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多