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

関数からのテキスト出力を新しいクエリとして使用する

    PREPAREの秘訣 CREATE FUNCTIONのような*テキスト文字列*(値)を受け取らないため、機能しません しますが、有効なステートメント (コード)。

    データを変換するには 実行可能コードに 動的SQL、つまりEXECUTEを使用する必要があります plpgsql関数またはDO 声明。戻り値の型が最初の関数myresult()の結果に依存しない限り、これは問題なく機能します。 。そうでなければ、私の前の答えで概説したように、22をキャッチするために戻ってきました:

    • postgresでストアドプロシージャの文字列結果を実行する方法

    重要な部分は、返品タイプを宣言することです。 (この場合は行タイプ)どういうわけか。 TABLEを作成できます 、TEMP TABLE またはTYPE 目的のために。または、プリペアドステートメントまたはリフカーサーを使用できます。

    プリペアドステートメントによる解決策

    あなたはとても親密でした。パズルの欠けている部分は、生成されたクエリを動的SQLで準備することです。 。

    ステートメントを動的に準備する関数

    この関数を一度作成します 。これは、関数の最適化された安全なバージョンですmyresult()

    CREATE OR REPLACE FUNCTION f_prep_query (_tbl regclass, _prefix text)
      RETURNS void AS 
    $func$
    BEGIN
       IF EXISTS (SELECT 1 FROM pg_prepared_statements WHERE name = 'stmt_dyn') THEN
          DEALLOCATE stmt_dyn;
       END IF;                 -- you my or may not need this safety check 
    
       EXECUTE (
         SELECT 'PREPARE stmt_dyn AS SELECT '
             || string_agg(quote_ident(attname), ',' ORDER BY attname)
             || ' FROM ' || _tbl
          FROM   pg_catalog.pg_attribute
          WHERE  attrelid = _tbl
          AND    attname LIKE _prefix || '%'
          AND    attnum > 0
          AND    NOT attisdropped
         );
    END
    $func$  LANGUAGE plpgsql;
    

    regclassを使用しています テーブル名パラメータ_tblの場合 SQLiに対して明確かつ安全にするため。詳細:

    • PostgreSQL関数パラメータとしてのテーブル名

    情報スキーマにはシステムカタログのoid列が含まれていないため、pg_catalog.pg_attributeに切り替えました。 information_schema.columnsの代わりに 。それも速いです。これには賛否両論があります:

    • 特定のスキーマにテーブルが存在するかどうかを確認する方法

    stmt_dynという名前のプリペアドステートメントの場合 すでに存在している、PREPARE 例外が発生します。それが許容できる場合は、システムビューのチェックを削除しますpg_prepared_statements および次のDEALLOCATE
    より高度なアルゴリズムを使用して、セッションごとに複数のプリペアドステートメントを管理したり、プリペアドステートメントの名前を追加のパラメータとして使用したり、クエリ文字列のMD5ハッシュを名前として使用したりすることもできますが、それだけではありません。この質問の範囲。

    PREPAREに注意してください トランザクションの範囲外で動作します 、一度PREPARE 成功すると、準備されたステートメントはセッションの存続期間中存在します。ラッピングトランザクションが中止された場合は、PREPARE 影響を受けません。 ROLLBACK できません 準備されたステートメントを削除します。

    動的クエリ実行

    2つ クエリですが、1つのみ サーバーを呼び出します。そして非常に効率的です。

    SELECT f_prep_query('tbl'::regclass, 'pre'::text);
    EXECUTE stmt_dyn;
    

    一時テーブルまたはカーソルを作成し、そこから選択/フェッチするよりも、最も単純なユースケースの方が簡単ではるかに効率的です(他のオプションになります)。

    SQLフィドル。



    1. 高可用性のためにMariaDBクラスターをデプロイする方法

    2. SQLServerデータベースをあるサーバーから別のサーバーに移動するためのヒント-RajanSinghによるSQLチュートリアル

    3. オラクル|重複レコードを削除する

    4. SpringのOracleデータソース構成