Не мога да си спомня кога за последен път всъщност трябваше да използвам изричен курсор за цикъл в plpgsql.
Използвайте имплицитния курсор на FOR
цикъл, това е много по-чисто:
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
$$;
Трябва да включите името на схемата, за да работи това за всички схеми (включително тези, които не са във вашия search_path
).
Освен това всъщност нуждате да използвате quote_ident()
или format()
с %I
или regclass
променлива за защита срещу SQL инжектиране. Името на таблица може да бъде почти всичко вътре в двойни кавички. Вижте:
- Име на таблица като параметър на функцията на PostgreSQL
Незначителна подробност:избягване на долната черта (_
) в LIKE
шаблон, за да го превърнете в буквално долно черта:tablename NOT LIKE 'pg\_%'
Как мога да го направя:
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
$$;
Заявка pg_catalog.pg_class
вместо tablename
, предоставя OID на таблицата.
Типът идентификатор на обекта regclass
е удобно за опростяване. n по-специално имената на таблици са в двойни кавички и се квалифицират автоматично, когато е необходимо (също предотвратява SQL инжектирането).
Тази заявка също така изключва временни таблици (временната схема е наречена pg_temp%
вътрешно).
За да включите само таблици от дадена схема:
AND n.nspname = 'public' -- schema name here, case-sensitive