関数は次のようになります:
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;
PostgreSQLの場合9.1 またはそれ以降は、format()
...
RETURN QUERY EXECUTE format('
SELECT *
FROM transactions
WHERE %I = $1
LIMIT $2', _col)
USING _val, _limit;
...
%I
quote_ident()
のような識別子をエスケープします 。
主なポイント:
-
識別子にパラメータを使用できないという動的SQLの制限にぶつかっていました。列名を使用してクエリ文字列を作成し、次に 実行してください。
-
ただし、値を使用してそれを行うことができます。
USING
の使用法を示しますEXECUTE
の句 。quote_ident()
:SQLインジェクションと特定の構文エラーを防ぎます。 -
また、機能を大幅に簡素化しました。
[RETURN QUERY EXECUTE][3]
コードをより短く、より速くします。行を返すだけであれば、ループする必要はありません。 -
名前付きの
IN
を使用します パラメータなので、クエリ文字列の$表記と混同しないでください。$1
および$2
クエリ文字列内で、USING
で提供される値を参照します 入力パラメータではなく、句。 -
SELECT *
に変更します とにかく宣言された戻りタイプと一致するように行全体を返す必要があるためです。 -
大事なことを言い忘れましたが、
SECURITY DEFINER
。
返品タイプ
行全体を返したくない場合、1つの便利な可能性は次のとおりです。
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)
RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...
そうすれば、すべての呼び出しで列定義リストを提供する必要がなくなり、次のように簡略化できます。
SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);