Jeg kan ikke huske, hvornår jeg sidst havde brug for at bruge en eksplicit markør til at sløjfe i plpgsql.
Brug den implicitte markør af en FOR
loop, det er meget renere:
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 skal inkludere skemanavnet for at få dette til at fungere for alle skemaer (inklusive dem, der ikke er i din search_path
).
Også, du faktisk bruger at bruge quote_ident()
eller format()
med %I
eller en regclass
variabel for at sikre mod SQL-injektion. Et tabelnavn kan være næsten hvad som helst inde i dobbelte anførselstegn. Se:
- Tabelnavn som en PostgreSQL-funktionsparameter
Mindre detaljer:Undgå understregningen (_
) i LIKE
mønster for at gøre det til et bogstaveligt understregning:tablename NOT LIKE 'pg\_%'
Sådan kan jeg gøre 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
$$;
Forespørgsel pg_catalog.pg_class
i stedet for tablename
, det giver tabellens OID.
Objektidentifikatortypen regclass
er praktisk at forenkle. Især tabelnavne anføres i dobbelte anførselstegn og skemakvalificeres, hvor det er nødvendigt automatisk (forhindrer også SQL-injektion).
Denne forespørgsel ekskluderer også midlertidige tabeller (temp-skemaet hedder pg_temp%
internt).
For kun at inkludere tabeller fra et givet skema:
AND n.nspname = 'public' -- schema name here, case-sensitive