改善の余地があります:
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
主なポイント
-
PostgreSQL8.4では
USING
が導入されましたEXECUTE
の句 、これはいくつかの理由で役立ちます。マニュアルの要約:コマンド文字列は、コマンドで
$1, $2
として参照されるパラメータ値を使用できます。 、など。これらの記号は、USING
で提供される値を参照します。 句。この方法は、データ値をテキストとしてコマンド文字列に挿入するよりも望ましい場合がよくあります。値をテキストに変換して戻すという実行時のオーバーヘッドを回避し、引用符やエスケープの必要がないため、SQLインジェクション攻撃の可能性がはるかに低くなります。IOW、
quote_literal()
でサニタイズした場合でも、パラメータのテキスト表現を使用してクエリ文字列を作成するよりも安全で高速です。 。$1, $2
に注意してください クエリ文字列で、USING
で指定された値を参照します 条項、ではない 関数パラメータに。 -
SELECT * FROM lookups.countries
を返す間 、RETURN
を簡略化できます 実証されたような宣言:RETURNS SETOF lookups.countries
PostgreSQLには、すべてのテーブルに対して自動的に定義された複合型があります。これを使って。その結果、関数はタイプによって異なり、テーブルを変更しようとするとエラーメッセージが表示されます。このような場合は、関数を削除して再作成してください。
これは望ましい場合と望ましくない場合があります-一般的にはそうです!テーブルを変更する場合は、副作用を認識しておく必要があります。あなたがそれを持っている方法では、あなたの関数は静かに壊れて、次の呼び出しで例外を引き起こします。
-
明示的なデフォルトを指定した場合 示されているような宣言の2番目のパラメーターについては、
ends_with
で上限を設定したくない場合に備えて、呼び出しを単純化できます(ただし、そうする必要はありません)。 。SELECT * FROM report_get_countries_new('Zaire');
代わりに:
SELECT * FROM report_get_countries_new('Zaire', NULL);
このコンテキストでは、関数のオーバーロードに注意してください。
-
言語名を引用しないでください
それが許容されるとしても(今のところ)。識別子です。'plpgsql' -
宣言時に変数を割り当てることができます。余分なステップを節約できます。
-
パラメータはヘッダーで指定されます。無意味な線を削除します:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;