Ich kann mich nicht erinnern, wann ich das letzte Mal tatsächlich einen expliziten Cursor für Schleifen in plpgsql benötigt habe.
Verwenden Sie den impliziten Cursor eines FOR
Schleife, das ist viel sauberer:
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
$$;
Sie müssen den Schemanamen angeben, damit dies für alle Schemas funktioniert (einschließlich derjenigen, die sich nicht in Ihrem search_path
befinden). ).
Außerdem brauchen Sie tatsächlich um quote_ident()
zu verwenden oder format()
mit %I
oder eine regclass
Variable zum Schutz vor SQL-Injection. Ein Tabellenname kann fast alles sein innerhalb doppelter Anführungszeichen. Siehe:
- Tabellenname als PostgreSQL-Funktionsparameter
Kleines Detail:Escapezeichen für den Unterstrich (_
) im LIKE
Muster, um es zu einem Literal zu machen Unterstrich:tablename NOT LIKE 'pg\_%'
Wie ich es machen könnte:
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
$$;
Fragen Sie pg_catalog.pg_class
ab statt tablename
, liefert es die OID der Tabelle.
Der Objektbezeichnertyp regclass
ist praktisch zu vereinfachen. Insbesondere werden Tabellennamen in doppelte Anführungszeichen gesetzt und ggf. automatisch schemaqualifiziert (verhindert auch SQL-Injection).
Diese Abfrage schließt auch temporäre Tabellen aus (das temporäre Schema heißt pg_temp%
intern).
So schließen Sie nur Tabellen aus einem bestimmten Schema ein:
AND n.nspname = 'public' -- schema name here, case-sensitive