如何从函数返回setof记录?

时间:2017-06-18 19:50:56

标签: postgresql plpgsql

我正在尝试创建一个将返回setof记录的函数。我想使用如下函数:

SELECT city_name FROM set_city(1, 1, 'ExampleName');

我的功能:

CREATE OR REPLACE FUNCTION set_city(_city_id integer, _country_id integer, _city_name varchar)
RETURNS SETOF RECORD
LANGUAGE plpgsql
as $$

DECLARE
        result record;

BEGIN
        IF EXISTS (SELECT 1 FROM geo_cities gc WHERE gc.id = _city_id)
        THEN
                UPDATE geo_cities
                SET country_id = _country_id, city_name = _city_name
                WHERE id = _city_id
                RETURNING * INTO result;
        ELSE
                INSERT INTO geo_cities(id, country_id, city_name)
                VALUES (_city_id, _country_id, _city_name)
                RETURNING * INTO result;
        END IF;
        -- It's wrong
        RETURN QUERY SELECT result;
END;
$$

我应该改变什么?

1 个答案:

答案 0 :(得分:1)

您可以更改return语句:

newBalance = oldBalance;

但是,返回“record”的函数需要列定义列表,因此您必须在每个查询中添加它:

...
        -- It's wrong
        -- RETURN QUERY SELECT result;
        RETURN NEXT result; -- that's good
...

实际上该函数返回SELECT city_name FROM set_city(1, 1, 'ExampleName') AS (id int, country_id int, city_name text); 类型的单行,而您不需要geo_cities

setof

请注意,您可以在单个SQL语句中获得相同的功能:

DROP FUNCTION set_city(_city_id integer, _country_id integer, _city_name varchar);

CREATE OR REPLACE FUNCTION set_city(_city_id integer, _country_id integer, _city_name varchar)
RETURNS geo_cities
LANGUAGE plpgsql
as $$
DECLARE
        result geo_cities;
BEGIN
        IF EXISTS (SELECT 1 FROM geo_cities gc WHERE gc.id = _city_id)
        THEN
                UPDATE geo_cities
                SET country_id = _country_id, city_name = _city_name
                WHERE id = _city_id
                RETURNING * INTO result;
        ELSE
                INSERT INTO geo_cities(id, country_id, city_name)
                VALUES (_city_id, _country_id, _city_name)
                RETURNING * INTO result;
        END IF;
        RETURN result;
END;
$$;

SELECT city_name FROM set_city(1, 1, 'ExampleName');