postgresql PL/pgSQL函数中的动态SELECT INTO

euoag5mw  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(223)

如何在Postgres的PL/pgSQL函数中编写动态SELECT INTO查询?
假设我有一个名为tb_name的变量,它从information_schema.tables填充到FOR循环中。现在我有一个名为tc的变量,它将为每个表获取行计数。我想要的东西如下:

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的数据类型应该是什么?

8yoxcaq7

8yoxcaq71#

CREATE OR REPLACE FUNCTION myfunc(_tbl_pattern text, _schema text = 'public')
  RETURNS void  -- or whatever you want to return
  LANGUAGE plpgsql AS
$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$;

字符串

备注

  • 我在所有的参数和变量前面加上了下划线(_),以避免与表列的命名冲突。只是一个有用的约定。
  • _tc应该是**bigint**,因为这是集合函数count()返回的值。
  • _tb_name的资料类型是从其父数据行动态衍生而来:information_schema.tables.table_name**%TYPE* 请参阅手册中的“复印类型”一章。
  • 您确定您只想在information_schema.tables中列出数据表吗?有道理,但要注意其中的含义。请参阅:
  • 如何检查给定模式中是否存在表
  • a_horse已经指向了手册和Andy provided a code example。这就是您将从EXECUTE动态查询传回的单一数据列或值指派给(row)变数的方式。一个 single 列(如本例中的count)自动从行类型中分解出来,因此我们可以直接赋值给标量变量tc--就像我们将一整行赋值给一个记录或行变量一样。相关信息:
  • 如何在PL/pgSQL中获取动态生成的字段名的值
    *结构描述限定动态查询中的数据表名称。在当前的search_path中可能存在同名的其他表,这将导致完全错误(并且非常混乱!)结果。鬼鬼祟祟的虫子!或者 this 模式根本不在search_path中,这会使函数立即引发异常。
  • search_path如何影响标识符解析和“当前模式”
    • 始终 * 正确引用标识符**以防止SQL注入和随机错误。架构和表必须 * 分别 * 用引号括起来!请参阅:
  • 表名作为PostgreSQL函数参数
  • 截断Posterre数据库中的所有表
  • 我在table_name ~ _tbl_pattern中使用了正则表达式运算符~,而不是table_name LIKE ('%' || _tbl_pattern || '%'),这样更简单。无论哪种方式,都要小心pattern参数中的特殊字符!请参阅:
  • PostgreSQL反向LIKE
  • 正则表达式或LIKE模式的转义函数
  • Pattern matching with LIKE, SIMILAR TO or regular expressions
  • 我在函数调用中为模式名称设置了一个默认值:_schema text = 'public'的数据。只是为了方便起见,你可能想要也可能不想要。请参阅:
  • 为类型分配默认值

处理您的意见:要传递 * 值 *,请使用USING子句,如下所示:

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


相关信息:

  • 在触发器函数中使用动态表名进行INSERT
q43xntqr

q43xntqr2#

看起来您需要FORMAT%I占位符,以便它将您的变量视为 identifier。另外,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

字符串

相关问题