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

PL/pgSQLで動的にクエリを実行する

    システム統計

    自分で作成する前に、システムテーブル pg_statistic または、ビュー pg_stats

    計算しようとしている統計の一部がすでに含まれている可能性があります。 ANALYZEが入力されます 、したがって、チェックする前に、新しい(または任意の)テーブルに対してそれを実行できます。

    -- ANALYZE tbl;  -- optionally, to init / refresh
    SELECT * FROM pg_stats
    WHERE tablename = 'tbl'
    AND   schemaname = 'public';
    

    汎用の動的plpgsql関数

    指定されたテーブルのすべての列の最小値を返したい 。関数(一般的なSQLなど)は、作成時、または少なくともポリモーフィックデータ型を使用して呼び出し時に戻り値を知る必要があるため、これは簡単な作業ではありません。

    この関数はすべてを自動的かつ安全に実行します。 すべてで機能します 集計関数min()である限り、テーブル すべての列に許可されます。しかし、あなたは必要 PL/pgSQLの使い方を知るために。

    CREATE OR REPLACE FUNCTION f_min_of(_tbl anyelement)
      RETURNS SETOF anyelement
      LANGUAGE plpgsql AS
    $func$
    BEGIN
    RETURN QUERY EXECUTE (
       SELECT format('SELECT (t::%2$s).* FROM (SELECT min(%1$s) FROM %2$s) t'
                    , string_agg(quote_ident(attname), '), min(' ORDER BY attnum)
                    , pg_typeof(_tbl)::text)
       FROM   pg_attribute
       WHERE  attrelid = pg_typeof(_tbl)::text::regclass
       AND    NOT attisdropped  -- no dropped (dead) columns
       AND    attnum > 0        -- no system columns
       );
    END
    $func$;
    

    電話(重要!):

    SELECT * FROM f_min_of(NULL::tbl);  -- tbl being the table name
    

    db <> fiddle こちら
    古い sqlfiddle

    これらの概念を理解する必要があります:

    • EXECUTEを使用したplpgsqlの動的SQL
    • ポリモーフィックタイプ
    • Postgresの行タイプとテーブルタイプ
    • SQLインジェクションを防ぐ方法
    • 集計関数
    • システムカタログ

    詳細な説明付きの関連回答:

    タイプの不一致に関する特別な問題

    私はPostgresを利用して、既存のすべてのテーブルの行タイプを定義しています。ポリモーフィックタイプの概念を使用して、1つを作成できます。 任意のテーブルで機能する関数。

    ただし、一部の集計関数は、基になる列と比較して、関連しているが異なるデータ型を返します。たとえば、 min(varchar_column) textを返します 、ビット互換ですが、正確には 同じデータ型。 PL / pgSQL関数はここに弱点があり、データ型を正確に主張します。 RETURNSで宣言されているとおり 句。割り当てキャストについては言うまでもなく、キャストの試みはなく、暗黙のキャストもありません。

    それは改善されるべきです。 Postgres9.3でテスト済み。 9.4で再テストしませんでしたが、この領域では何も変わっていないと確信しています。

    そこで、この構成が回避策として登場します。 :

    SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;
    

    行全体を基になるテーブルの行タイプに明示的にキャストすることにより、割り当てキャストにすべての列の元のデータ型を取得するように強制します。

    これは、一部の集計関数では失敗する可能性があります。 sum() 数値を返します sum(bigint_column)の場合 基本データ型をオーバーフローする合計に対応するため。 bigintにキャストバック 失敗するかもしれません...



    1. Extendsを使用してエンティティに関するクエリを台無しにするDoctrine

    2. findAllの続編は関数ではありません

    3. PHPでSQLクエリを保護するための最良の方法

    4. MysqlコマンドがOSX10.7に見つかりません