PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Loop em tabelas com PL/pgSQL no Postgres 9.0+


Não me lembro da última vez que precisei usar um cursor explícito para fazer um loop no plpgsql.
Use o cursor implícito de um FOR loop, isso é muito mais limpo:
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
$$;

Você precisa incluir o nome do esquema para fazer isso funcionar para todos os esquemas (incluindo aqueles que não estão em seu search_path ).

Além disso, você precisa para usar quote_ident() ou format() com %I ou uma regclass variável para proteção contra injeção de SQL. Um nome de tabela pode ser quase qualquer coisa entre aspas duplas. Ver:
  • Nome da tabela como parâmetro de função do PostgreSQL

Detalhe menor:escape do sublinhado (_ ) no LIKE padrão para torná-lo um literal sublinhado:tablename NOT LIKE 'pg\_%'

Como posso fazer isso:

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

Consulta pg_catalog.pg_class em vez de tablename , ele fornece o OID da tabela.

O tipo de identificador de objeto regclass é útil para simplificar. Em particular, os nomes das tabelas são colocados entre aspas duplas e qualificados pelo esquema quando necessário automaticamente (também evita a injeção de SQL).

Esta consulta também exclui tabelas temporárias (o esquema temporário chama-se pg_temp% internamente).

Para incluir apenas tabelas de um determinado esquema:
    AND    n.nspname = 'public' -- schema name here, case-sensitive