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 字符串传递!参见:
- Define table and column names as arguments in a plpgsql function?
- SQL injection in Postgres functions vs prepared queries
我正在将 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 字符串传递!参见:
- Define table and column names as arguments in a plpgsql function?
- SQL injection in Postgres functions vs prepared queries