Er is ruimte voor verbeteringen:
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
Belangrijkste punten
-
PostgreSQL 8.4 introduceerde de
USING
clausule voorEXECUTE
, wat om verschillende redenen nuttig is. Samenvatting in de handleiding:De opdrachtreeks kan parameterwaarden gebruiken, waarnaar in de opdracht wordt verwezen als
$1, $2
, enz. Deze symbolen verwijzen naar waarden die zijn opgegeven in deUSING
clausule. Deze methode heeft vaak de voorkeur boven het invoegen van gegevenswaarden in de opdrachtreeks als tekst:het vermijdt runtime-overhead van het converteren van de waarden naar tekst en terug, en het is veel minder vatbaar voor aanvallen met SQL-injectie, omdat citeren of ontsnappen niet nodig is.IOW, het is veiliger en sneller dan het bouwen van een queryreeks met tekstweergave van parameters, zelfs wanneer deze is opgeschoond met
quote_literal()
.
Merk op dat$1, $2
in de queryreeks verwijzen naar de opgegeven waarden in deUSING
clausule, niet naar de functieparameters. -
Terwijl u
SELECT * FROM lookups.countries
return retourneert , kunt u deRETURN
. vereenvoudigen verklaring zoals aangetoond:RETURNS SETOF lookups.countries
In PostgreSQL is er automatisch een samengesteld type gedefinieerd voor elke tabel. Gebruik het. Het effect is dat de functie afhankelijk is van het type en je een foutmelding krijgt als je de tabel probeert te wijzigen. Laat de functie vallen en maak deze opnieuw aan in een dergelijk geval.
Dit kan al dan niet wenselijk zijn - over het algemeen is het dat wel! U wilt op de hoogte worden gesteld van bijwerkingen als u tabellen wijzigt. Zoals je het hebt, zou je functie stil breken en een uitzondering veroorzaken bij de volgende aanroep.
-
Als u een expliciete standaard . opgeeft voor de tweede parameter in de declaratie, zoals aangetoond, kun je (maar hoeft niet) de aanroep te vereenvoudigen voor het geval je geen bovengrens wilt instellen met
ends_with
.SELECT * FROM report_get_countries_new('Zaire');
in plaats van:
SELECT * FROM report_get_countries_new('Zaire', NULL);
Houd in deze context rekening met functieoverbelasting.
-
Citeer niet de taalnaam
zelfs als dat wordt getolereerd (voorlopig). Het is een identificatie.'plpgsql' -
U kunt een variabele toewijzen op het moment van declaratie. Bespaart een extra stap.
-
Parameters worden genoemd in de kop. Laat de onzinnige regels vallen:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;