Saya tidak ingat kapan terakhir kali saya benar-benar perlu menggunakan kursor eksplisit untuk mengulang di plpgsql.
Gunakan kursor implisit dari FOR
loop, itu jauh lebih bersih:
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
$$;
Anda harus menyertakan nama skema agar ini berfungsi untuk semua skema (termasuk yang tidak ada di search_path
Anda ).
Juga, Anda sebenarnya membutuhkan untuk menggunakan quote_ident()
atau format()
dengan %I
atau regclass
variabel untuk melindungi terhadap injeksi SQL. Nama tabel bisa hampir semua dalam tanda kutip ganda. Lihat:
- Nama tabel sebagai parameter fungsi PostgreSQL
Detail kecil:hindari garis bawah (_
) di bagian LIKE
pola untuk membuatnya menjadi literal garis bawah:tablename NOT LIKE 'pg\_%'
Bagaimana saya bisa melakukannya:
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
$$;
Kueri pg_catalog.pg_class
bukannya tablename
, ini memberikan OID tabel.
Jenis pengenal objek regclass
berguna untuk menyederhanakan. n khususnya, nama tabel dikutip ganda dan memenuhi syarat skema jika diperlukan secara otomatis (juga mencegah injeksi SQL).
Kueri ini juga mengecualikan tabel sementara (skema temp bernama pg_temp%
secara internal).
Untuk hanya menyertakan tabel dari skema tertentu:
AND n.nspname = 'public' -- schema name here, case-sensitive