Det finns utrymme för förbättringar:
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
Huvudpunkter
-
PostgreSQL 8.4 introducerade
USING
sats förEXECUTE
, vilket är användbart av flera skäl. Sammanfattning i manualen:Kommandosträngen kan använda parametervärden, som refereras till i kommandot som
$1, $2
, etc. Dessa symboler refererar till värden som finns iUSING
klausul. Denna metod är ofta att föredra framför att infoga datavärden i kommandosträngen som text:den undviker runtime overhead för att konvertera värdena till text och tillbaka, och den är mycket mindre benägen för SQL-injektionsattacker eftersom det inte finns något behov av att citera eller fly.IOW, det är säkrare och snabbare än att bygga en frågesträng med textrepresentation av parametrar, även när det saneras med
quote_literal()
.
Observera att$1, $2
i frågesträngen hänvisar till de angivna värdena iUSING
klausul, inte till funktionsparametrarna. -
Medan du returnerar
SELECT * FROM lookups.countries
, kan du förenklaRETURN
deklaration som visas:RETURNS SETOF lookups.countries
I PostgreSQL finns en sammansatt typ definierad för varje tabell automatiskt. Använd den. Effekten är att funktionen beror på typen och du får ett felmeddelande om du försöker ändra tabellen. Släpp och återskapa funktionen i ett sådant fall.
Detta kan eller kanske inte är önskvärt - i allmänhet är det så! Du vill bli medveten om biverkningar om du ändrar tabeller. Som du har det kommer din funktion att gå sönder tyst och göra ett undantag vid nästa samtal.
-
Om du anger en uttrycklig standard för den andra parametern i deklarationen som visas, kan du (men behöver inte) förenkla anropet om du inte vill sätta en övre gräns med
ends_with
.SELECT * FROM report_get_countries_new('Zaire');
istället för:
SELECT * FROM report_get_countries_new('Zaire', NULL);
Var medveten om funktionsöverbelastning i detta sammanhang.
-
Citera inte språknamnet
även om det tolereras (för nu). Det är en identifierare.'plpgsql' -
Du kan tilldela en variabel vid deklarationstillfället. Sparar ett extra steg.
-
Parametrar namnges i rubriken. Släpp de meningslösa raderna:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;