Uw functie kan er als volgt uitzien:
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)
RETURNS SETOF transactions AS
$BODY$
BEGIN
RETURN QUERY EXECUTE '
SELECT *
FROM transactions
WHERE ' || quote_ident(_col) || ' = $1
LIMIT $2'
USING _val, _limit;
END;
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;
IN PostgreSQL 9.1 of later is dat eenvoudiger met format()
...
RETURN QUERY EXECUTE format('
SELECT *
FROM transactions
WHERE %I = $1
LIMIT $2', _col)
USING _val, _limit;
...
%I ontsnapt aan identifiers zoals quote_ident() .
Belangrijkste punten:
-
U liep tegen de beperking van dynamische SQL aan dat u geen parameters voor id's kunt gebruiken. U moet de queryreeks bouwen met de kolomnaam en vervolgens voer het uit.
-
Dat kun je wel doen met waarden. Ik demonstreer het gebruik van de
USINGclausule voorEXECUTE. Let ook op het gebruik vanquote_ident():voorkomt SQL-injectie en bepaalde syntaxisfouten. -
Ik heb je functie ook grotendeels vereenvoudigd.
[RETURN QUERY EXECUTE][3]maakt je code korter en sneller. U hoeft niet te herhalen als u alleen de rij terugstuurt. -
Ik gebruik de naam
INparameters, zodat u niet in de war raakt met de $-notatie in de queryreeks.$1en$2verwijzen in de queryreeks naar de waarden in deUSINGclausule, niet naar de invoerparameters. -
Ik verander naar
SELECT *omdat je toch de hele rij moet retourneren om overeen te komen met het opgegeven retourtype. -
Last but not least:denk goed na wat de handleiding te zeggen heeft over functies die zijn gedeclareerd
SECURITY DEFINER.
RETOURTYPE
Als u niet de hele rij wilt retourneren, is een handige mogelijkheid:
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)
RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...
Dan hoeft u niet bij elke oproep een kolomdefinitielijst te verstrekken en kunt u vereenvoudigen tot:
SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);