Tôi không thể nhớ lần cuối cùng tôi thực sự cần sử dụng con trỏ rõ ràng để lặp lại trong plpgsql.
Sử dụng con trỏ ngầm của FOR
vòng lặp, điều đó rõ ràng hơn nhiều:
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
$$;
Bạn cần bao gồm tên lược đồ để làm cho nó hoạt động cho tất cả các lược đồ (bao gồm cả những lược đồ không có trong search_path
của bạn ).
Ngoài ra, bạn thực sự cần để sử dụng quote_ident()
hoặc format()
với %I
hoặc một regclass
biến để bảo vệ chống lại việc đưa vào SQL. Tên bảng có thể là hầu hết mọi thứ bên trong dấu ngoặc kép. Xem:
- Tên bảng dưới dạng tham số hàm PostgreSQL
Chi tiết nhỏ:thoát dấu gạch dưới (_
) trong LIKE
mẫu để biến nó thành một nghĩa đen gạch dưới:tablename NOT LIKE 'pg\_%'
Tôi có thể làm như thế nào:
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
$$;
Truy vấn pg_catalog.pg_class
thay vì tablename
, nó cung cấp OID của bảng.
Loại mã định danh đối tượng regclass
là tiện dụng để đơn giản hóa. n cụ thể, tên bảng được đặt trong dấu ngoặc kép và đủ điều kiện giản đồ khi cần thiết một cách tự động (cũng ngăn chặn việc đưa vào SQL).
Truy vấn này cũng loại trừ các bảng tạm thời (lược đồ tạm thời được đặt tên là pg_temp%
nội bộ).
Để chỉ bao gồm các bảng từ một lược đồ nhất định:
AND n.nspname = 'public' -- schema name here, case-sensitive