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