Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 将动态参数数传递给函数时发生数组错误_Postgresql_Stored Procedures_Plpgsql_Dynamic Sql - Fatal编程技术网

Postgresql 将动态参数数传递给函数时发生数组错误

Postgresql 将动态参数数传递给函数时发生数组错误,postgresql,stored-procedures,plpgsql,dynamic-sql,Postgresql,Stored Procedures,Plpgsql,Dynamic Sql,我正在尝试创建一个函数,以接收已创建模式中的表名和该表中的多个列名(动态列数),并返回一个表,其中所有列都位于一个唯一列中,每个列的值用逗号分隔 我正在尝试这个: CREATE OR REPLACE PROCEDURE public.matching(IN table text, VARIADIC column_names text[]) LANGUAGE 'plpgsql' AS $BODY$DECLARE column_text text; BEGIN EXECUTE

我正在尝试创建一个函数,以接收已创建模式中的表名和该表中的多个列名(动态列数),并返回一个表,其中所有列都位于一个唯一列中,每个列的值用逗号分隔

我正在尝试这个:

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$;
这将返回一个错误: 错误:«{»处或附近的语法错误 第1行:选择数组到字符串({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
select *
from matching('some_table', 'one', 'two', 'three');
我还为新列使用了列别名,以便新表具有已定义的名称。请注意,我将列名放入SQL字符串的方式无法正确处理需要双引号的标识符(但无论如何都应避免使用双引号)


如果要“返回表”,则函数可能是更好的解决方案:

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$;
然后你可以这样使用它:

create table temp1 as select concat_ws(',', one,two,three) as everything from some_table
select *
from matching('some_table', 'one', 'two', 'three');

谢谢你的问题!!但是,使用这个脚本,我的问题没有得到解决,不是吗?我的目标是创建一个具有唯一列的表。该列的值是我作为参数在函数中传递的所有列的值,用逗号分隔。我对我的问题做了一些更改,可能不清楚。抱歉。