Der er plads til forbedringer:
CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
, ends_with text = NULL)
RETURNS SETOF lookups.countries AS
$func$
DECLARE
sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
IF ends_with IS NOT NULL THEN
sql := sql || ' AND country_name <= $2';
END IF;
RETURN QUERY EXECUTE sql
USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;
-- the rest is default settings
Vigtige punkter
-
PostgreSQL 8.4 introducerede
USING
klausul forEXECUTE
, hvilket er nyttigt af flere grunde. Opsummering i manualen:Kommandostrengen kan bruge parameterværdier, der refereres til i kommandoen som
$1, $2
osv. Disse symboler henviser til værdier, der er angivet iUSING
klausul. Denne metode er ofte at foretrække frem for at indsætte dataværdier i kommandostrengen som tekst:den undgår driftsomkostninger ved at konvertere værdierne til tekst og tilbage, og den er meget mindre tilbøjelig til SQL-injektionsangreb, da der ikke er behov for at citere eller undslippe.IOW, det er sikrere og hurtigere end at bygge en forespørgselsstreng med tekstrepræsentation af parametre, selv når det renses med
quote_literal()
.
Bemærk at$1, $2
i forespørgselsstrengen henvises til de angivne værdier iUSING
klausul, ikke til funktionsparametrene. -
Mens du returnerer
SELECT * FROM lookups.countries
, kan du forenkleRETURN
erklæring som vist:RETURNS SETOF lookups.countries
I PostgreSQL er der en sammensat type defineret for hver tabel automatisk. Brug det. Effekten er, at funktionen afhænger af typen, og du får en fejlmeddelelse, hvis du forsøger at ændre tabellen. Drop og genskab funktionen i et sådant tilfælde.
Dette er måske eller måske ikke ønskeligt - generelt er det det! Du ønsker at blive gjort opmærksom på bivirkninger, hvis du ændrer tabeller. Som du har det, vil din funktion gå i stykker lydløst og rejse en undtagelse ved det næste opkald.
-
Hvis du angiver en eksplicit standard for den anden parameter i erklæringen som vist, kan du (men behøver ikke) forenkle opkaldet, hvis du ikke ønsker at sætte en øvre grænse med
ends_with
.SELECT * FROM report_get_countries_new('Zaire');
i stedet for:
SELECT * FROM report_get_countries_new('Zaire', NULL);
Vær opmærksom på funktionsoverbelastning i denne sammenhæng.
-
Angiv ikke sprognavnet
selvom det er tolereret (indtil videre). Det er en identifikator.'plpgsql' -
Du kan tildele en variabel på deklarationstidspunktet. Gemmer et ekstra trin.
-
Parametre er navngivet i overskriften. Drop de useriøse linjer:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;