Tot*_*tor 17 postgresql variables loops plpgsql tablename
我想遍历所有表来计算每个表中的行数.以下查询给我一个错误:
DO $$
DECLARE
tables CURSOR FOR
SELECT tablename FROM pg_tables
WHERE tablename NOT LIKE 'pg_%'
ORDER BY tablename;
tablename varchar(100);
nbRow int;
BEGIN
FOR tablename IN tables LOOP
EXECUTE 'SELECT count(*) FROM ' || tablename INTO nbRow;
-- Do something with nbRow
END LOOP;
END$$;
Run Code Online (Sandbox Code Playgroud)
错误:
Run Code Online (Sandbox Code Playgroud)ERROR: syntax error at or near ")" LINE 1: SELECT count(*) FROM (sql_features) ^ QUERY: SELECT count(*) FROM (sql_features) CONTEXT: PL/pgSQL function inline_code_block line 8 at EXECUTE statement
sql_features是我的数据库中的表名.我已经尝试使用quote_ident()但无济于事.
Erw*_*ter 28
我不记得上次我真的需要在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
$$;
Run Code Online (Sandbox Code Playgroud)
您需要包含模式名称,以使其适用于所有模式(包括那些不在您的模式中search_path).
此外,您实际上需要使用quote_ident()或format()使用%I以防止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
$$;
Run Code Online (Sandbox Code Playgroud)
查询pg_catalog.pg_class代替tablename,它提供表的OID.
的对象标识符类型regclass是很方便的,以简化,特别是,表名是双引号和模式限定在必要时自动地(也防止SQL注入).
此查询还排除临时表(临时模式以pg_temp%内部命名).
如果只需要来自给定模式的表:
AND n.nspname = 'public' -- schema name here, case-sensitive
Run Code Online (Sandbox Code Playgroud)a_h*_*ame 16
游标返回记录而不是标量值,因此"tablename"不是字符串变量.
连接将记录转换为看起来像这样的字符串(sql_features).如果您选择了例如带有tablename的schemaname,则记录的文本表示将是(public,sql_features).
因此,您需要访问记录中的列以创建SQL语句:
DO $$
DECLARE
tables CURSOR FOR
SELECT tablename
FROM pg_tables
WHERE tablename NOT LIKE 'pg_%'
ORDER BY tablename;
nbRow int;
BEGIN
FOR table_record IN tables LOOP
EXECUTE 'SELECT count(*) FROM ' || table_record.tablename INTO nbRow;
-- Do something with nbRow
END LOOP;
END$$;
Run Code Online (Sandbox Code Playgroud)
您可能希望使用WHERE schemaname = 'public'而不是not like 'pg_%'排除Postgres系统表.
| 归档时间: |
|
| 查看次数: |
60236 次 |
| 最近记录: |