PostgreSQL:遍历文本数组并执行 SQL

PostgreSQL: Iterating over array of text and executing SQL

我正在将 tables 从一个架构复制到另一个架构。我正在尝试传递要复制的 table 的名称参数。但是当我执行 CALL 时,没有在 Schema 中创建 table。

命令:CALL copy_table('firstname', 'tableName1,tableName2,tableName3');

CREATE OR REPLACE PROCEDURE copy_table(user VARCHAR(50), strs TEXT)
LANGUAGE PLPGSQL
AS $$
DECLARE
    my_array TEXT;
BEGIN
    FOR my_array IN
        SELECT string_to_array(strs, ',')
    LOOP
        EXECUTE 'CREATE TABLE ' || user || '.' || my_array || ' (LIKE public.' || my_array || ' INCLUDING ALL)';
    END LOOP;
$$

你能帮忙吗?谢谢。

函数string_to_array returns一个数组值。遍历数组是由 FOREACH 命令执行的,而不是 FOR.

查看文档:

https://www.postgresql.org/docs/14/plpgsql-control-structures.html#PLPGSQL-FOREACH-ARRAY

CREATE FUNCTION sum(int[]) RETURNS int8 AS $$
DECLARE
  s int8 := 0;
  x int;
BEGIN
  FOREACH x IN ARRAY 
  LOOP
    s := s + x;
  END LOOP;
  RETURN s;
END;
$$ LANGUAGE plpgsql;

像 Simon 建议的那样用 FOREACH 遍历一个数组。或者在旧(或任何)版本中使用 FOR。参见:

  • Iterating over integer[] in PL/pgSQL

通常,set-based 解决方案更短更快,但是:

CREATE OR REPLACE PROCEDURE copy_tables(_schema text, VARIADIC _tables text[])
  LANGUAGE plpgsql AS
$proc$
BEGIN
   EXECUTE
   (SELECT string_agg(format('CREATE TABLE %1$I.%2$I (LIKE public.%2$I INCLUDING ALL)', _schema, t), E';\n')
    FROM   unnest(_tables) t);
END
$proc$;

关于VARIADIC

  • Return rows matching elements of input array in plpgsql function

调用、传递 table 姓名列表:

CALL copy_tables('firstname', 'tableName1', 'tableName2', 'tableName3');

或者,传递真正的数组:

CALL copy_tables('foo', VARIADIC '{tableName1,tableName2,tableName3}');

或者,传递(和转换)comma-separated 字符串(您的原始输入):

CALL copy_tables('foo', VARIADIC string_to_array('tableName1,tableName2,tableName3', ','));

我使用 format() 安全地连接 SQL 字符串。请注意,标识符必须作为 case-sensitive 字符串传递!参见: