Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 在Postgres 9.0+;_Postgresql_Variables_Loops_Plpgsql_Tablename - Fatal编程技术网

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