最後に、plpgsql でループするために明示カーソルを実際に使用する必要があったのはいつか思い出せません。loop
の暗黙のカーソルを使用します。これははるかにクリーンです。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
。
また、 SQL インジェクションから保護するために、実際にはorを変数と一緒に使用する必要があります。テーブル名は、二重引用符内のほとんど何でもかまいません。見る:quote_ident()
format()
%I
regclass
マイナーな詳細:パターン_
内のアンダースコア ( ) をエスケープして、リテラルアンダースコアにします。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