如何从select查询中返回值?

时间:2017-07-13 22:51:39

标签: postgresql postgis

我想计算两个城市之间的距离。我有以下功能:

CREATE OR REPLACE FUNCTION calc_distance_for_cities(fromCityId bigint, toCityId bigint) RETURNS integer LANGUAGE plpgsql as $$

    DECLARE
            fromCityCoords Geometry;
            toCityCoords Geometry;

    BEGIN
            SELECT * FROM geo_cities WHERE geo_cities.id = fromCityId RETURNING coords INTO fromCityCoords;
            SELECT * FROM geo_cities WHERE geo_cities.id = toCityId RETURNING coords INTO toCityCoords;
            SELECT ST_Distance(fromCityCoords, toCityCoords, true)
    END;

    $$

我做错了什么?

1 个答案:

答案 0 :(得分:0)

TL; DR你"做错了"两件事:returns integer应为returns float,最后select ..应为return ..

详细说明:

RETURN从PL / pgSQL函数返回一个值 - 您需要使用它而不是最后SELECTst_distance(..)根据http://postgis.refractions.net/docs/ST_Distance.html返回float值,因此您的第一行需要returns float

试试这个:

CREATE OR REPLACE FUNCTION calc_distance_for_cities(fromCityId bigint, toCityId bigint) RETURNS float LANGUAGE plpgsql as $$

    DECLARE
            fromCityCoords Geometry;
            toCityCoords Geometry;

    BEGIN
            SELECT coords INTO fromCityCoords FROM geo_cities WHERE geo_cities.id = fromCityId;
            SELECT coords INTO toCityCoords FROM geo_cities WHERE geo_cities.id = toCityId;
            RETURN ST_Distance(fromCityCoords, toCityCoords, true);
    END;

    $$;

此外,这个函数实际上并不需要PL / pgSQL语言,并且可以在纯SQL中轻松实现,CTE(https://www.postgresql.org/docs/current/static/queries-with.html):

create or replace function calc_distance_for_cities(int8, int8) returns float as $$
  with _from(city_coords) as (
    select coords from geo_cities where geo_cities.id = $1
  ), _to(city_coords) as (
    select coords from geo_cities where geo_cities.id = $2
  )
  select st_distance(_from.city_coords, _to.city_coords)
  from _from, _to;
$$ language sql;

甚至没有CTE:

create or replace function calc_distance_for_cities(int8, int8) returns float as $$
  select st_distance(
    (select coords from geo_cities where geo_cities.id = $1),
    (select coords from geo_cities where geo_cities.id = $2)
  );
$$ language sql;