PL/pgSQL 函数中的动态 SELECT INTO

Dynamic SELECT INTO in PL/pgSQL function

如何在 Postgres 中的 PL/pgSQL 函数中编写动态 SELECT INTO 查询?

假设我有一个名为 tb_name 的变量,它填充在 information_schema.tablesFOR 循环中。现在我有一个名为 tc 的变量,它将计算每个 table 的行数。我想要如下内容:

FOR tb_name in select table_name from information_schema.tables where table_schema='some_schema' and table_name like '%1%'
LOOP
EXECUTE FORMAT('select count(*) into' || tc 'from' || tb_name);
END LOOP

在这种情况下,tb_nametc 的数据类型应该是什么?

您似乎想要 FORMAT%I 占位符,以便它将您的变量视为 标识符 。此外,INTO 子句应该 在准备好的语句之外

FOR tb_name in select table_name from information_schema.tables where table_schema='some_schema' and table_name like '%1%'
LOOP
  EXECUTE FORMAT('select count(*) from %I', tb_name) INTO tc;
END LOOP
CREATE OR REPLACE FUNCTION myfunc(_tbl_pattern text, _schema text = 'public')
  RETURNS void AS  -- or whatever you want to return
$func$
DECLARE
   _tb_name information_schema.tables.table_name%TYPE;  -- currently varchar
   _tc      bigint;  -- count() returns bigint
BEGIN
   FOR _tb_name IN
      SELECT table_name
      FROM   information_schema.tables
      WHERE  table_schema = _schema
      AND    table_name   ~ _tbl_pattern  -- see below!
   LOOP
      EXECUTE format('SELECT count(*) FROM %I.%I', _schema, _tb_name)
      INTO _tc;      

      -- do something with _tc
   END LOOP;
END
$func$  LANGUAGE plpgsql;

备注

  • 我在所有参数和变量前加了下划线 (_),以避免 命名 与 table 列发生冲突。只是一个有用的约定。

  • _tc 应该是 bigint,因为这就是聚合函数 count() returns。

  • _tb_name 的数据类型动态派生自其父列:information_schema.tables.table_name%TYPE。见章节 Copying Types in the manual.

  • 您确定只想要 table 中列出的 information_schema.tables 吗?有道理,但要注意含义。参见:

    • How to check if a table exists in a given schema
  • already pointed to the manual and 。这就是您如何 分配 单个行或从 EXECUTE 动态查询返回的值到(行)变量。 列(如示例中的count)自动从行类型中分解出来,因此我们可以直接分配给标量变量tc - 在相同的我们将整行分配给记录或行变量的方式。相关:

  • Schema-qualify 动态查询中的 table 名称。当前 search_path 中可能还有其他 table 同名,这将导致完全错误(并且非常混乱!)的结果没有模式限定。偷偷摸摸的虫子!或者 this 模式根本不在 search_path 中,这会使函数立即引发异常。

    • How does the search_path influence identifier resolution and the "current schema"
  • 总是 正确引用标识符以防止SQL注入和随机错误。 Schema和table要分开引用!参见:

    • Table name as a PostgreSQL function parameter
    • Truncating all tables in a Postgres database
  • 我在table_name ~ _tbl_pattern中使用正则表达式运算符~而不是table_name LIKE ('%' || _tbl_pattern || '%'),这样更简单。无论哪种方式,都要警惕模式参数中的特殊字符!参见:

  • 我在函数调用中为架构名称设置了一个默认值:_schema text = 'public'。只是为了方便,您可能需要也可能不需要。参见:

    • Assigning default value for type

寻址:传递,使用USING子句,如:

EXECUTE format('SELECT count(*) FROM %I.%I
                WHERE some_column = ', _schema, _tb_name,column_name)
USING user_def_variable;

相关:

  • INSERT with dynamic table name in trigger function