1. Implicit cursor
It's almost always better to use the implicit cursor of a FOR
loop than to resort to a somewhat slower and unwieldy explicit cursor. I have written thousands of plpgsql functions and only a hand full of times explicit cursors made any sense.
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;
Aside: there is nothing in the function that would need volatility VOLATILE
. Use STABLE
.
2. Set-based approach
It's almost always better to use a set-based approach if possible. Use RETURN QUERY
to return as set from a query directly.
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;
3. SQL function
For the simple case (probably a simplification), you might also use a simple SQL function or even just the query:
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;
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…