数组错误将动态数量的参数传递给函数
Array error passing dynamic number of parameters to function
我正在尝试创建一个函数来接收我的模式中已创建的 table 的名称以及此 table 中的多个列名称(动态列数)和 return a table,所有列都在一个唯一的列中,每列的值用逗号分隔。
我正在尝试这个:
CREATE OR REPLACE PROCEDURE public.matching(IN table text, VARIADIC column_names text[])
LANGUAGE 'plpgsql'
AS $BODY$DECLARE
column_text text;
BEGIN
EXECUTE format ($$ SELECT array_to_string(%s, ' ')$$, column_names) into column_text;
EXECUTE format ($$ CREATE TABLE temp1 AS
SELECT concat(%s, ' ') FROM %s $$, column_text, table);
END;$BODY$;
这return一个错误:
错误:«{» 处或附近的语法错误
第 1 行:SELECT array_to_string({city,address}, ' ')
哪个是错误的?
我提出不同但相似的代码。
使用以下脚本:
CREATE OR REPLACE PROCEDURE public.test(IN p_old_table text, IN p_old_column_names text[], IN p_new_table text)
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
old_column_list text;
ctas_stmt text;
BEGIN
old_column_list = array_to_string(p_old_column_names,',');
RAISE NOTICE 'old_column_list=%', old_column_list;
ctas_stmt = format('CREATE TABLE %s AS SELECT %s from %s', p_new_table, old_column_list, p_old_table);
RAISE NOTICE 'ctas_stmt=%', ctas_stmt;
EXECUTE ctas_stmt;
END;
$BODY$;
--
create table t(x int, y text, z timestamp, z1 text);
insert into t values (1, 'OK', current_timestamp, null);
select * from t;
--
call test('t',ARRAY['x','y','z'], 'tmp');
--
\d tmp;
select * from tmp;
我有以下执行:
CREATE OR REPLACE PROCEDURE public.test(IN p_old_table text, IN p_old_column_names text[], IN p_new_table text)
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
old_column_list text;
ctas_stmt text;
BEGIN
old_column_list = array_to_string(p_old_column_names,',');
RAISE NOTICE 'old_column_list=%', old_column_list;
ctas_stmt = format('CREATE TABLE %s AS SELECT %s from %s', p_new_table, old_column_list, p_old_table);
RAISE NOTICE 'ctas_stmt=%', ctas_stmt;
EXECUTE ctas_stmt;
END;
$BODY$;
CREATE PROCEDURE
create table t(x int, y text, z timestamp, z1 text);
CREATE TABLE
insert into t values (1, 'OK', current_timestamp, null);
INSERT 0 1
select * from t;
x | y | z | z1
---+----+----------------------------+----
1 | OK | 2020-04-14 11:37:28.641328 |
(1 row)
call test('t',ARRAY['x','y','z'], 'tmp');
psql:tvar.sql:24: NOTICE: old_column_list=x,y,z
psql:tvar.sql:24: NOTICE: ctas_stmt=CREATE TABLE tmp AS SELECT x,y,z from t
CALL
Table "public.tmp"
Column | Type | Collation | Nullable | Default
--------+-----------------------------+-----------+----------+---------
x | integer | | |
y | text | | |
z | timestamp without time zone | | |
select * from tmp;
x | y | z
---+----+----------------------------
1 | OK | 2020-04-14 11:37:28.641328
(1 row)
如果您简化动态的生成 SQL,事情会变得更容易:
CREATE OR REPLACE PROCEDURE public.matching(IN table_name text, VARIADIC column_names text[])
LANGUAGE plpgsql
AS
$BODY$
DECLARE
l_sql text;
BEGIN
l_sql := format($s$
create table temp1 as
select concat_ws(',', %s) as everything
from %I
$s$, array_to_string(column_names, ','), table_name);
raise notice 'Running %', l_sql;
EXECUTE l_sql;
END;
$BODY$;
所以如果你传入 'some_table'
和 {'one', 'two', 'three'}
生成的 SQL 将如下所示:
create table temp1 as select concat_ws(',', one,two,three) as everything from some_table
我还为新列使用了列别名,这样新的 table 就有了定义的名称。请注意,我将列名放入 SQL 字符串的方式无法正确处理需要双引号的标识符(但无论如何都应避免)
如果您想 "return a table",那么函数可能是更好的解决方案:
CREATE OR REPLACE function matching(IN table_name text, VARIADIC column_names text[])
returns table (everything text)
LANGUAGE plpgsql
AS
$BODY$
DECLARE
l_sql text;
BEGIN
l_sql := format($s$
select concat_ws(',', %s) as everything
from %I
$s$, array_to_string(column_names, ','), table_name);
return query execute l_sql;
END;
$BODY$;
那么你可以这样使用它:
select *
from matching('some_table', 'one', 'two', 'three');
我正在尝试创建一个函数来接收我的模式中已创建的 table 的名称以及此 table 中的多个列名称(动态列数)和 return a table,所有列都在一个唯一的列中,每列的值用逗号分隔。
我正在尝试这个:
CREATE OR REPLACE PROCEDURE public.matching(IN table text, VARIADIC column_names text[])
LANGUAGE 'plpgsql'
AS $BODY$DECLARE
column_text text;
BEGIN
EXECUTE format ($$ SELECT array_to_string(%s, ' ')$$, column_names) into column_text;
EXECUTE format ($$ CREATE TABLE temp1 AS
SELECT concat(%s, ' ') FROM %s $$, column_text, table);
END;$BODY$;
这return一个错误: 错误:«{» 处或附近的语法错误 第 1 行:SELECT array_to_string({city,address}, ' ')
哪个是错误的?
我提出不同但相似的代码。
使用以下脚本:
CREATE OR REPLACE PROCEDURE public.test(IN p_old_table text, IN p_old_column_names text[], IN p_new_table text)
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
old_column_list text;
ctas_stmt text;
BEGIN
old_column_list = array_to_string(p_old_column_names,',');
RAISE NOTICE 'old_column_list=%', old_column_list;
ctas_stmt = format('CREATE TABLE %s AS SELECT %s from %s', p_new_table, old_column_list, p_old_table);
RAISE NOTICE 'ctas_stmt=%', ctas_stmt;
EXECUTE ctas_stmt;
END;
$BODY$;
--
create table t(x int, y text, z timestamp, z1 text);
insert into t values (1, 'OK', current_timestamp, null);
select * from t;
--
call test('t',ARRAY['x','y','z'], 'tmp');
--
\d tmp;
select * from tmp;
我有以下执行:
CREATE OR REPLACE PROCEDURE public.test(IN p_old_table text, IN p_old_column_names text[], IN p_new_table text)
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
old_column_list text;
ctas_stmt text;
BEGIN
old_column_list = array_to_string(p_old_column_names,',');
RAISE NOTICE 'old_column_list=%', old_column_list;
ctas_stmt = format('CREATE TABLE %s AS SELECT %s from %s', p_new_table, old_column_list, p_old_table);
RAISE NOTICE 'ctas_stmt=%', ctas_stmt;
EXECUTE ctas_stmt;
END;
$BODY$;
CREATE PROCEDURE
create table t(x int, y text, z timestamp, z1 text);
CREATE TABLE
insert into t values (1, 'OK', current_timestamp, null);
INSERT 0 1
select * from t;
x | y | z | z1
---+----+----------------------------+----
1 | OK | 2020-04-14 11:37:28.641328 |
(1 row)
call test('t',ARRAY['x','y','z'], 'tmp');
psql:tvar.sql:24: NOTICE: old_column_list=x,y,z
psql:tvar.sql:24: NOTICE: ctas_stmt=CREATE TABLE tmp AS SELECT x,y,z from t
CALL
Table "public.tmp"
Column | Type | Collation | Nullable | Default
--------+-----------------------------+-----------+----------+---------
x | integer | | |
y | text | | |
z | timestamp without time zone | | |
select * from tmp;
x | y | z
---+----+----------------------------
1 | OK | 2020-04-14 11:37:28.641328
(1 row)
如果您简化动态的生成 SQL,事情会变得更容易:
CREATE OR REPLACE PROCEDURE public.matching(IN table_name text, VARIADIC column_names text[])
LANGUAGE plpgsql
AS
$BODY$
DECLARE
l_sql text;
BEGIN
l_sql := format($s$
create table temp1 as
select concat_ws(',', %s) as everything
from %I
$s$, array_to_string(column_names, ','), table_name);
raise notice 'Running %', l_sql;
EXECUTE l_sql;
END;
$BODY$;
所以如果你传入 'some_table'
和 {'one', 'two', 'three'}
生成的 SQL 将如下所示:
create table temp1 as select concat_ws(',', one,two,three) as everything from some_table
我还为新列使用了列别名,这样新的 table 就有了定义的名称。请注意,我将列名放入 SQL 字符串的方式无法正确处理需要双引号的标识符(但无论如何都应避免)
如果您想 "return a table",那么函数可能是更好的解决方案:
CREATE OR REPLACE function matching(IN table_name text, VARIADIC column_names text[])
returns table (everything text)
LANGUAGE plpgsql
AS
$BODY$
DECLARE
l_sql text;
BEGIN
l_sql := format($s$
select concat_ws(',', %s) as everything
from %I
$s$, array_to_string(column_names, ','), table_name);
return query execute l_sql;
END;
$BODY$;
那么你可以这样使用它:
select *
from matching('some_table', 'one', 'two', 'three');