2017-06-18 93 views
0

我想創建一個函數,它將返回setof記錄。我想使用的功能如下:如何從函數返回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

你可以改變返回語句:

... 
     -- 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

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'); 

請注意,您可以在單個SQL語句中獲得相同的功能:

INSERT INTO geo_cities(id, country_id, city_name) 
VALUES (1, 1, 'ExampleName') 
ON CONFLICT (id) DO UPDATE SET 
    country_id = excluded.country_id, 
    city_name = excluded.city_name 
RETURNING *;