sql >> データベース >  >> RDS >> PostgreSQL

plpgsql関数の動的ORDERBYおよびASC/DESC

    私はこのようにします:

    CREATE OR REPLACE FUNCTION list(
          _category varchar(100)
        , _limit int
        , _offset int
        , _order_by varchar(100)
        , _order_asc_desc text = 'ASC')  -- last param with default value
      RETURNS TABLE(id int, name varchar, clientname varchar, totalcount bigint)
      LANGUAGE plpgsql AS
    $func$
    DECLARE
       _empty text := '';
    BEGIN
       -- Assert valid _order_asc_desc
       IF upper(_order_asc_desc) IN ('ASC', 'DESC', 'ASCENDING', 'DESCENDING') THEN
          -- proceed
       ELSE
          RAISE EXCEPTION 'Unexpected value for parameter _order_asc_desc.
                           Allowed: ASC, DESC, ASCENDING, DESCENDING. Default: ASC';
       END IF;
       
       RETURN QUERY EXECUTE format(
         'SELECT id, name, clientname, count(*) OVER() AS full_count
          FROM   design_list
          WHERE ($1 = $2 OR category ILIKE $1) 
          ORDER  BY %I %s
          LIMIT  %s
          OFFSET %s'
        , _order_by, _order_asc_desc, _limit, _offset)
       USING _category, _empty;
    END
    $func$;
    

    コア機能:format() クエリ文字列を安全かつエレガントに連結します。関連:

    ASC / DESC (またはASCENDING /DESCENDING )は固定キーワードです。手動チェックを追加しました(IF ... )そして後で単純な%sと連結します 。それは1つです 正当な入力を主張する方法。便宜上、予期しない入力に対するエラーメッセージとパラメータのデフォルトを追加したため、関数のデフォルトはASCになります。 呼び出しで最後のパラメーターが省略された場合。関連:

    Pavelの有効なアドレスコメント_limitを連結します および_offset 直接なので、クエリはすでにこれらのパラメータで計画されています。

    _limit および_offset integerです パラメータなので、プレーンな%sを使用できます SQLインジェクションの危険なし。連結する前に、妥当な値(負の値と高すぎる値を除く)を表明することをお勧めします...

    その他の注意事項:
    • 一貫した命名規則を使用します。すべてのパラメーターと変数の前にアンダースコア_を付けました 、一部だけではありません 。

    • EXECUTE内でテーブル修飾を使用しない 、関係するテーブルは1つだけであり、EXECUTE 個別のスコープがあります。

    • 明確にするために、いくつかのパラメーターの名前を変更しました。 _order_by _sort_byの代わりに; _order_asc_desc _orderの代わりに 。



    1. JavascriptOracleでの順序のような配列の並べ替え

    2. pg_stat_activityのクエリは切り捨てられますか?

    3. MySQLの期間によるグループ化の結果

    4. MySQLで特定の日付の月末日を見つける方法