PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Schleife auf Tabellen mit PL/pgSQL in Postgres 9.0+

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