Я не могу вспомнить, когда в последний раз мне действительно нужно было использовать явный курсор для зацикливания в 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-инъекций. Имя таблицы может быть почти любым в двойных кавычках. Видеть:
Незначительная деталь: избегайте подчеркивания (_
) в шаблоне 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
удобен для упрощения. В частности, имена таблиц заключаются в двойные кавычки и при необходимости автоматически уточняются схемой (также предотвращает SQL-инъекция).
Этот запрос также исключает временные таблицы (временная схема имеет внутреннее имя pg_temp%
).
Чтобы включить только таблицы из данной схемы:
AND n.nspname = 'public' -- schema name here, case-sensitive
person
Erwin Brandstetter
schedule
07.03.2013