Postgresql 在Postgres 9.0+;
我想在我所有的表中循环计算每个表中的行数。以下查询获取一个错误:Postgresql 在Postgres 9.0+;,postgresql,variables,loops,plpgsql,tablename,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 tab
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$$;
错误:
sql\u features
是my DB中的表名。我已经尝试使用quote_ident()
,但没有效果。光标返回的是记录,而不是标量值,因此“tablename”不是字符串变量
串联将记录转换为如下所示的字符串(sql\U特性)。如果您选择了例如带有表名的schemaname,则记录的文本表示形式应该是(public,sql\u 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$$;
您可能希望使用
WHERE schemaname='public'
而不是而不是像'pg\%'
那样排除Postgres系统表 我不记得上一次在plpgsql中实际需要使用显式游标进行循环是什么时候了。使用a的隐式光标,这样更清晰:
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
$$;
您需要包含架构名称,以便对所有架构(包括那些不在搜索路径中的架构)执行此操作
此外,您实际上需要使用or和%I
或一个变量来防止SQL注入。表名几乎可以是双引号内的任何内容。见:
次要细节:在LIKE
模式中转义下划线(
),使其成为文字下划线:表名不像“pg\\\%”
我该如何做:
似乎,在Postgre9.6中,在第一个示例中也(最好)需要与“sql%”不同的。在第二个示例中,n.nspname!='需要信息_schema'
。另一个区别是第二个忽略了临时表(由于pg%
条件)。@MasaSakano:所有优点,我都相应地更新了(有一些改进)。
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
$$;
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
$$;
AND n.nspname = 'public' -- schema name here, case-sensitive