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

Postgres9.0以降でPL/pgSQLを使用してテーブルをループする

    plpgsqlでループするために明示カーソルを実際に使用する必要があった最後の時間を思い出せません。
    FORの暗黙カーソルを使用してください ループ、それははるかにクリーンです:

    DO
    $$
    DECLARE
       rec   record;
       nbrow bigint;
    BEGIN
       FOR rec IN
          SELECT *
          FROM   pg_tables
          WHERE  tablename NOT LIKE 'pg\_%'
          ORDER  BY tablename
       LOOP
          EXECUTE 'SELECT count(*) FROM '
            || quote_ident(rec.schemaname) || '.'
            || quote_ident(rec.tablename)
          INTO nbrow;
          -- Do something with nbrow
       END LOOP;
    END
    $$;
    

    すべてのスキーマ(search_pathにないものを含む)でこれを機能させるには、スキーマ名を含める必要があります 。

    また、実際には必要 quote_ident()を使用するには またはformat() %Iを使用 またはregclass SQLインジェクションから保護するための変数。テーブル名はほぼすべてにすることができます 二重引用符で囲みます。参照:

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

    マイナーな詳細:アンダースコアをエスケープします(_LIKE 文字通りにするためのパターン アンダースコア:tablename NOT LIKE 'pg\_%'

    どうすればよいですか:

    DO
    $$
    DECLARE
        tbl   regclass;
        nbrow bigint;
    BEGIN
       FOR tbl IN
          SELECT c.oid
          FROM   pg_class     c
          JOIN   pg_namespace n ON n.oid = c.relnamespace
          WHERE  c.relkind = 'r'
          AND    n.nspname NOT LIKE 'pg\_%'         -- system schema(s)
          AND    n.nspname <> 'information_schema'  -- information schema
          ORDER  BY n.nspname, c.relname
       LOOP
          EXECUTE 'SELECT count(*) FROM ' || tbl INTO nbrow;
          -- raise notice '%: % rows', tbl, nbrow;
       END LOOP;
    END
    $$;
    

    クエリpg_catalog.pg_class tablenameの代わりに 、テーブルのOIDを提供します。

    オブジェクト識別子タイプregclass 単純化するのに便利です。特に、テーブル名は二重引用符で囲まれ、必要に応じて自動的にスキーマ修飾されます(SQLインジェクションも防止されます)。

    このクエリは一時テーブルも除外します(一時スキーマの名前はpg_temp%です) 内部的に)。

    特定のスキーマのテーブルのみを含めるには:

        AND    n.nspname = 'public' -- schema name here, case-sensitive
    


    1. PostgreSQLで2つの日付間の時系列を生成する

    2. 日付と時刻のデータのバケット化

    3. mysqlで名前文字列を分割する方法は?

    4. ActivityMonitorを介してデータベースとインスタンスを監視する| SQLServerのパフォーマンスのトラブルシューティング-2