【问题标题】:postgresql error - ERROR: input is out of rangepostgresql 错误 - 错误:输入超出范围
【发布时间】:2025-12-06 17:00:01
【问题描述】:

下面的函数不断返回此错误消息。我认为可能是 double_precision 字段类型导致了这种情况,我尝试使用 CAST,但不是这样,或者我做得不对...帮助?

这是错误:

ERROR:  input is out of range
CONTEXT:  PL/pgSQL function "calculate_distance" line 7 at RETURN

********** Error **********

ERROR: input is out of range
SQL state: 22003
Context: PL/pgSQL function "calculate_distance" line 7 at RETURN

函数如下:

 CREATE OR REPLACE FUNCTION calculate_distance(character varying, 
double precision, double precision, 
double precision, double precision)

      RETURNS double precision AS
    $BODY$ 
            DECLARE earth_radius double precision; 

            BEGIN 
                    earth_radius := 3959.0; 

                    RETURN earth_radius * acos(sin($2 / 57.2958) * 
sin($4 / 57.2958) + cos($2/ 57.2958) * cos($4 / 57.2958) 
* cos(($5 / 57.2958) - ($3 / 57.2958)));
            END; 
            $BODY$
      LANGUAGE 'plpgsql' VOLATILE
      COST 100;
    ALTER FUNCTION calculate_distance(character varying, 
double precision, double precision, double precision, 
double precision) OWNER TO postgres;



    //I tried changing (unsuccessfully) that RETURN line to: 

    RETURN CAST( (earth_radius * acos(sin($2 / 57.2958) 
* sin($4 / 57.2958) + cos($2/ 57.2958) * cos($4 / 57.2958) 
* cos(($5 / 57.2958) - ($3 / 57.2958))) ) AS text);

【问题讨论】:

    标签: postgresql function


    【解决方案1】:

    有点晚了,但遇到了同样的问题,这是因为 acos 参数在 [-1,1] 之外(可能是 1.01) 在计算 ACOS 之前,您应该将该值转换为 INTEGER

    像这样:

    
            RETURN  (earth_radius * acos(CAST ((sin($2 / 57.2958) 
    sin($4 / 57.2958) + cos($2/ 57.2958) * cos($4 / 57.2958) 
     cos(($5 / 57.2958) - ($3 / 57.2958)) AS INTEGER)) );
    

    【讨论】:

    • 这不可能,你最终会做出一切01
    【解决方案2】:

    看看这个解决方案:

    http://www.postgresql.org/message-id/12376732.post@talk.nabble.com

    问题确实是 ACOS() 超出了 [-1,1] 范围,并且 发生这种情况是因为它正在计算相同的距离 LAT,LONG 对(同一位置)

    我添加了一个 WHERE L1.ID L2.ID 来停止反身计算。

    Martijn van Oosterhout 写道:

    2007 年 8 月 18 日星期六下午 3:21:02 -0700,dustov 写道:

    我的数据库刚刚出现这个新错误,我不知道为什么(因为我 没有故意对此表进行任何更改)。有没有人有 一个 知道哪个输入超出范围——或者问题可能是什么?

    您的查询中唯一我能想象的超出范围的是 ACOS() 需要介于 -1 和 1 之间(否则结果 会很复杂)。

    我会尝试看看 ACOS 的论点是什么,但它可能是 四舍五入的一些极端情况。

    希望这会有所帮助,

    我在计算坐标之间的距离时遇到了同样的错误,但上面的提示解决了我的问题。

    【讨论】:

      【解决方案3】:

      这是由于浮点舍入错误将值设为 >1。

      在使用 ACOS 之前,使用 least and greatest 将值限制在 -1 到 1 的范围内

      acos(least(greatest(...),-1),1));
      

      完全替换:

       CREATE OR REPLACE FUNCTION calculate_distance(character varying, 
      double precision, double precision, 
      double precision, double precision)
      
            RETURNS double precision AS
          $BODY$ 
                  DECLARE earth_radius double precision; 
      
                  BEGIN 
                          earth_radius := 3959.0; 
      
                          RETURN earth_radius *
      acos(least(greatest(
          sin($2 / 57.2958) * 
          sin($4 / 57.2958) + cos($2/ 57.2958) * cos($4 / 57.2958) 
          * cos(($5 / 57.2958) - ($3 / 57.2958))
      ),-1),1));
                  END; 
                  $BODY$
            LANGUAGE 'plpgsql' VOLATILE
            COST 100;
          ALTER FUNCTION calculate_distance(character varying, 
      double precision, double precision, double precision, 
      double precision) OWNER TO postgres;
      

      【讨论】:

        【解决方案4】:

        我遇到了同样的问题,我无法安装 contrib 模块(我不是管理员)。

        您可以在这里查看: http://en.wikipedia.org/wiki/Great-circle_distance

        一个数值稳定的公式(对于非对映点)如下:

        RETURN earth_radius * (2.*asin(sqrt((power(sin(radians(($4-$2)/2.)),2))+
        (cos(radians($4))*cos(radians($2))*power(sin(radians(($5-$3)/2.)),2)))));
        

        如果您需要一个通用公式,您可以尝试实现 Wikipedia 页面中解释的 atan2 之一。

        【讨论】:

          【解决方案5】:

          如果坐标相同,您将收到异常“[22003] 错误:输入超出范围”。为了防止它捕获异常并返回 0,如下所示:

          EXCEPTION
          WHEN numeric_value_out_of_range
          THEN RETURN 0;
          

          【讨论】: