sql >> Databasteknik >  >> RDS >> PostgreSQL

Slinga på bord med PL/pgSQL i Postgres 9.0+

Jag kommer inte ihåg när jag senast behövde använda en explicit markör för att loopa i plpgsql.
Använd den implicita markören för en FOR loop, det är mycket renare:

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

Du måste inkludera schemanamnet för att detta ska fungera för alla scheman (inklusive de som inte finns i din search_path ).

Dessutom behöver du för att använda quote_ident() eller format() med %I eller en regclass variabel för att skydda mot SQL-injektion. Ett tabellnamn kan vara nästan vad som helst inuti dubbla citattecken. Se:

  • Tabellnamn som en PostgreSQL-funktionsparameter

Mindre detalj:Undvik understrecket (_ ) i LIKE mönster för att göra det bokstavligt understreck:tablename NOT LIKE 'pg\_%'

Hur jag kan göra det:

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

Fråga pg_catalog.pg_class istället för tablename , den tillhandahåller tabellens OID.

Objektidentifieraren typ regclass är praktiskt att förenkla. Speciellt tabellnamn är dubbla citattecken och schemakvalificerade vid behov automatiskt (förhindrar också SQL-injektion).

Den här frågan exkluderar även tillfälliga tabeller (tempschemat heter pg_temp% internt).

För att endast inkludera tabeller från ett givet schema:

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


  1. Använder du namngivna instanser? Testa din DAC-anslutning!

  2. Ansluter AnySQL Maestro till Salesforce.com

  3. Ansluter RazorSQL till Salesforce.com

  4. HAProxy Connections vs MySQL Connections - Vad du bör veta