sql >> Databáze >  >> RDS >> PostgreSQL

Smyčka na tabulkách s PL/pgSQL v Postgresu 9.0+

Nepamatuji si, kdy jsem naposledy skutečně potřeboval použít explicitní kurzor pro opakování v plpgsql.
Použijte implicitní kurzor FOR smyčka, to je mnohem čistší:

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

Aby to fungovalo pro všechna schémata (včetně těch, která nejsou ve vaší search_path), musíte uvést název schématu ).

Ve skutečnosti také potřebujete použít quote_ident() nebo format() s %I nebo regclass proměnná pro ochranu proti vložení SQL. Název tabulky může být téměř cokoliv uvnitř dvojitých uvozovek. Viz:

  • Název tabulky jako parametr funkce PostgreSQL

Menší detail:escape podtržítko (_ ) v LIKE vzor, ​​aby to bylo doslovné podtržítko:tablename NOT LIKE 'pg\_%'

Jak bych to mohl udělat:

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

Dotaz pg_catalog.pg_class místo tablename , poskytuje OID tabulky.

Typ identifikátoru objektu regclass je užitečné zjednodušit. Konkrétně jsou názvy tabulek uváděny do dvojitých uvozovek a v případě potřeby jsou automaticky kvalifikovány pro schéma (také zabraňuje vkládání SQL).

Tento dotaz také vylučuje dočasné tabulky (dočasné schéma se jmenuje pg_temp% interně).

Chcete-li zahrnout pouze tabulky z daného schématu:

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


  1. Jak zacházet s booleovskými hodnotami v SQLite pomocí JavaScript proxy

  2. Chyba MySQL/PHP:[2002] Obvykle je povoleno pouze jedno použití každé adresy soketu (protokol/síťová adresa/port)

  3. Je možné specifikovat schéma při připojení k postgres s JDBC?

  4. Recenze knihy :Benjamin Nevarez:Query Tuning &Optimization