2017-06-18 2 views
0

Ich versuche, eine Funktion zu erstellen, die setof Datensatz zurückgibt. Ich möchte die Funktion wie folgt verwenden:Wie man Datensatz von der Funktion zurückgibt?

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

Meine Funktion:

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; 
$$ 

Was sollte ich ändern?

Antwort

1

Sie konnten die return-Anweisung ändern:

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

jedoch eine Spaltendefinitionsliste für Funktionen erforderlich ist "record" Rückkehr, so würden Sie es in jeder Abfrage hinzufügen:

SELECT city_name FROM set_city(1, 1, 'ExampleName') 
    AS (id int, country_id int, city_name text); 

In der Tat gibt die Funktion eine einzelne Zeile des Typs geo_cities und Sie brauchen nicht 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'); 

Beachten Sie, dass Sie die gleiche Funktionalität in einer einzigen SQL-Anweisung erhalten können:

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 *; 
Verwandte Themen