Ошибка массива при передаче Dynami c количество параметров в функцию - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь создать функцию, которая получит имя таблицы в моей уже созданной схеме и несколько имен столбцов в этой таблице (Dynami c количество столбцов) и вернет таблицу со всеми столбцами в уникальный столбец со значением каждого столбца, разделенных запятой.

Я пытаюсь это:

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$;

Это возвращает ошибку: ОШИБКА: синтаксическая ошибка в или около «{» LINE 1: SELECT array_to_string ({city, address}, '')

, что является ошибкой?

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

Если вы упростите генерацию динамического c 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

Я также использовал псевдоним столбца для нового столбца, чтобы новая таблица имела определенное имя. Обратите внимание, что способ, которым я помещаю имена столбцов в строку SQL, не будет правильно работать с идентификаторами, которые требуют двойных кавычек (но их все равно следует избегать)


Если вы хотите «вернуть 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');
0 голосов
/ 14 апреля 2020

Я предлагаю другой, но похожий код.

С помощью следующего скрипта:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...