sql >> Database >  >> RDS >> PostgreSQL

Loop op tabellen met PL/pgSQL in Postgres 9.0+

Ik kan me niet herinneren wanneer ik voor het laatst een expliciete cursor moest gebruiken voor looping in plpgsql.
Gebruik de impliciete cursor van een FOR lus, dat is veel schoner:

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
$$;

U moet de schemanaam opnemen om dit voor alle schema's te laten werken (inclusief diegene die niet in uw search_path staan ).

Ook heb je eigenlijk nodig om quote_ident() te gebruiken of format() met %I of een regclass variabele om te beschermen tegen SQL-injectie. Een tabelnaam kan bijna alles zijn tussen dubbele aanhalingstekens. Zie:

  • Tabelnaam als een PostgreSQL-functieparameter

Klein detail:escape the underscore (_ ) in de LIKE patroon om er een letterlijk van te maken underscore:tablename NOT LIKE 'pg\_%'

Hoe ik het zou kunnen doen:

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
$$;

Zoekopdracht pg_catalog.pg_class in plaats van tablename , het geeft de OID van de tafel.

Het object-ID type regclass is handig om te vereenvoudigen. In het bijzonder worden tabelnamen dubbel geciteerd en waar nodig automatisch gekwalificeerd voor het schema (verhindert ook SQL-injectie).

Deze query sluit ook tijdelijke tabellen uit (tijdelijk schema heet pg_temp% intern).

Om alleen tabellen van een bepaald schema op te nemen:

    AND    n.nspname = 'public' -- schema name here, case-sensitive


  1. Oracle JDeveloper 12c gebruiken met Oracle Database 12c op Oracle Cloud Platform, deel 2

  2. 🆕 Eerste overzicht van SQL Server 2022 - Top 5 nieuwe functies (Bonus 5-functies)

  3. 3 manieren om de maandnaam van een datum in MariaDB te krijgen

  4. Door de gebruiker gedefinieerde variabelen in PostgreSQL