J'essaie d'utiliser des curseurs pour une requête qui joint plusieurs tables. J'ai vu que pour Oracle, il existe un enregistrement basé sur le curseur. Lorsque j'essaie de même pour Postgres, cela génère une erreur. Comment puis-je faire de même dans Postgres?
CREATE OR REPLACE FUNCTION avoidable_states()
RETURNS SETOF varchar AS
$BODY$
DECLARE
xyz CURSOR FOR select * from address ad
join city ct on ad.city_id = ct.city_id;
xyz_row RECORD;
BEGIN
open xyz;
LOOP
fetch xyz into xyz_row;
exit when xyz_row = null;
if xyz_row.city like '%hi%' then
return next xyz_row.city;
end if;
END LOOP;
close xyz;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
L'erreur que j'obtiens est:
ERROR: relation "xyz" does not exist CONTEXT: compilation of PL/pgSQL function "avoidable_states" near line 4
Utilisez simplement le type RECORD
:
DECLARE
...
cur_row RECORD;
BEGIN
...
FETCH xyz INTO cur_row;
EXIT WHEN NOT FOUND;
IF cur_row.city LIKE 'CH%' THEN
...
Il est presque toujours préférable d'utiliser le curseur implicite d'une boucle FOR
plutôt que de recourir à une boucle un peu plus lente et un curseur explicite peu maniable. J'ai écrit des milliers de fonctions plpgsql et seule une main pleine de curseurs explicites a du sens.
CREATE OR REPLACE FUNCTION avoidable_states()
RETURNS SETOF varchar AS
$func$
DECLARE
rec record;
BEGIN
FOR rec IN
SELECT *
FROM address ad
JOIN city ct USING (city_id)
LOOP
IF rec.city LIKE '%hi%' THEN
RETURN NEXT rec.city;
END IF;
END LOOP;
END
$func$ LANGUAGE plpgsql STABLE;
A part: il n'y a rien dans la fonction qui aurait besoin de volatilité VOLATILE
. Utilisez STABLE
.
Il est presque toujours préférable d'utiliser une approche basée sur un ensemble si possible. Utilisation RETURN QUERY
pour retourner directement comme défini à partir d'une requête.
CREATE OR REPLACE FUNCTION avoidable_states()
RETURNS SETOF varchar AS
$func$
BEGIN
RETURN QUERY
SELECT ct.city
FROM address ad
JOIN city ct USING (city_id)
WHERE ct.city LIKE '%hi%';
END
$func$ LANGUAGE plpgsql STABLE;
Pour le cas simple (probablement une simplification), vous pouvez également utiliser un simple fonction SQL ou même simplement la requête:
CREATE OR REPLACE FUNCTION avoidable_states()
RETURNS SETOF varchar AS
$func$
SELECT ct.city
FROM address ad
JOIN city ct USING (city_id)
WHERE ct.city LIKE '%hi%';
$func$ LANGUAGE sql STABLE;