Nepamatuji si, kdy jsem naposledy skutečně potřeboval použít explicitní kurzor pro opakování v plpgsql.
Použijte implicitní kurzor FOR
smyčka, to je mnohem čistší:
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
$$;
Aby to fungovalo pro všechna schémata (včetně těch, která nejsou ve vaší search_path
), musíte uvést název schématu ).
Ve skutečnosti také potřebujete použít quote_ident()
nebo format()
s %I
nebo regclass
proměnná pro ochranu proti vložení SQL. Název tabulky může být téměř cokoliv uvnitř dvojitých uvozovek. Viz:
- Název tabulky jako parametr funkce PostgreSQL
Menší detail:escape podtržítko (_
) v LIKE
vzor, aby to bylo doslovné podtržítko:tablename NOT LIKE 'pg\_%'
Jak bych to mohl udělat:
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
$$;
Dotaz pg_catalog.pg_class
místo tablename
, poskytuje OID tabulky.
Typ identifikátoru objektu regclass
je užitečné zjednodušit. Konkrétně jsou názvy tabulek uváděny do dvojitých uvozovek a v případě potřeby jsou automaticky kvalifikovány pro schéma (také zabraňuje vkládání SQL).
Tento dotaz také vylučuje dočasné tabulky (dočasné schéma se jmenuje pg_temp%
interně).
Chcete-li zahrnout pouze tabulky z daného schématu:
AND n.nspname = 'public' -- schema name here, case-sensitive