Det är inget fel med en plpgsql-funktion för något lite mer komplicerat. Den enda situationen där prestanda kan drabbas är när en plpgsql-funktion kapslas, eftersom frågeplaneraren inte kan optimera den inneslutna koden ytterligare i sammanhanget med den yttre frågan, vilket kan eller inte kan göra den långsammare.
Mer detaljer i detta senare. svar:
- Skillnaden mellan språk sql och språk plpgsql i PostgreSQL-funktioner
I det aktuella fallet är det mycket enklare än många CASE
satser i en fråga:
CREATE OR REPLACE FUNCTION get_stuff(_param text, _orderby text, _limit int)
RETURNS SETOF stuff AS
$func$
BEGIN
RETURN QUERY EXECUTE '
SELECT *
FROM stuff
WHERE col = $1
ORDER BY ' || quote_ident(_orderby) || ' ASC
LIMIT $2'
USING _param, _limit;
END
$func$ LANGUAGE plpgsql;
Ring:
SELECT * FROM get_stuff('hello', 'col2', 100);
Anteckningar
Använd RETURN QUERY EXECUTE
för att returnera resultatet av frågan på en gång.
Använd quote_ident()
för identifierare för att skydda mot SQLi.
Eller format()
för något mer komplicerat. Se:
- Tabellnamn som en PostgreSQL-funktionsparameter
Skicka parametervärden med USING
klausul för att undvika casting, citering och SQLi igen.
Var försiktig så att du inte skapar namnkonflikter mellan parametrar och kolumnnamn. Jag prefixerade parameternamn med ett understreck (_
) i exemplet. Bara min personliga preferens.
Din andra funktion efter redigeringen kan inte fungera, eftersom du bara returnerar parent
medan returtypen deklareras SETOF stuff
. Du kan deklarera vilken som helst returtyp du gillar, men faktiska returvärden måste matcha deklarationen. Du kanske vill använda RETURNS TABLE
för det.