Der er ikke noget galt med en plpgsql-funktion til noget lidt mere komplekst. Den eneste situation, hvor ydeevnen kan lide, er, når en plpgsql-funktion er indlejret, fordi forespørgselsplanlæggeren ikke kan optimere den indeholdte kode yderligere i sammenhæng med den ydre forespørgsel, hvilket muligvis gør den langsommere eller ikke.
Flere detaljer i dette senere. svar:
- Forskellen mellem sprog sql og sprog plpgsql i PostgreSQL-funktioner
I den foreliggende sag er det meget enklere end mange CASE
klausuler i en forespørgsel:
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 til:
SELECT * FROM get_stuff('hello', 'col2', 100);
Bemærkninger
Brug RETURN QUERY EXECUTE
for at returnere resultaterne af forespørgslen på én gang.
Brug quote_ident()
for identifikatorer til at beskytte mod SQLi.
Eller format()
til noget mere komplekst. Se:
- Tabelnavn som en PostgreSQL-funktionsparameter
Send parameterværdier med USING
klausul for at undgå casting, citering og SQLi igen.
Pas på ikke at skabe navnekonflikter mellem parametre og kolonnenavne. Jeg indsatte parameternavne med en understregning (_
) i eksemplet. Bare min personlige præference.
Din anden funktion efter redigeringen kan ikke fungere, fordi du kun returnerer parent
mens returtypen er erklæret SETOF stuff
. Du kan erklære hvilken som helst returtype, du kan lide, men de faktiske returværdier skal svare til deklarationen. Du vil måske bruge RETURNS TABLE
for det.