Vaše funkce může vypadat takto:
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;
V PostgreSQL 9.1 nebo později je to jednodušší s formátem format()
...
RETURN QUERY EXECUTE format('
SELECT *
FROM transactions
WHERE %I = $1
LIMIT $2', _col)
USING _val, _limit;
...
%I
escapuje identifikátory jako quote_ident()
.
Hlavní body:
-
Naráželi jste na omezení dynamického SQL, že nemůžete použít parametry pro identifikátory. Musíte vytvořit řetězec dotazu s názvem sloupce a pak provést.
-
Můžete to udělat s hodnotami. Ukazuji použití
USING
klauzule proEXECUTE
. Všimněte si také použitíquote_ident()
:zabraňuje vkládání SQL a určitým syntaktickým chybám. -
Také jsem značně zjednodušil vaši funkci.
[RETURN QUERY EXECUTE][3]
zkrátí a zrychlí váš kód. Není třeba opakovat, pokud vše, co uděláte, je vrátit řádek. -
Používám s názvem
IN
parametry, abyste se nepletli s $-notací v řetězci dotazu.$1
a$2
uvnitř řetězce dotazu odkazují na hodnoty uvedené vUSING
klauzule, nikoli vstupním parametrům. -
Změním na
SELECT *
protože stejně musíte vrátit celý řádek, aby odpovídal deklarovanému typu návratu. -
V neposlední řadě:Nezapomeňte zvážit, co příručka říká o funkcích deklarovaných
SECURITY DEFINER
.
TYP VRÁCENÍ
Pokud nechcete vrátit celý řádek, jedna pohodlná možnost je:
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)
RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...
Pak nemusíte při každém volání poskytovat seznam definic sloupců a můžete to zjednodušit na:
SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);