Как получить имя столбца из массива для запроса select в Postgres

Вопрос:

Мне нужен запрос таблицы, получающей имя столбца из массива… что-то вроде этого

$$
DECLARE
column varchar[] := array['column1','column2','column3'];
_row record;
BEGIN
FOR i IN 1 .. array_length(column, 1)
LOOP
RAISE NOTICE '%: %', i, column[i];
select t.column[i] into _row from table t;
RAISE NOTICE '%: %', i, _row.column[i];
END LOOP;
END;
$$ language plpgsql;

Ты понял? Является ли это возможным?

Ответ №1

Всякий раз, когда вам нужно преобразовать ввод пользователя в identifiers или code в инструкции SQL, вам нужен динамический SQL. Либо соедините выражение в своем клиенте, либо отправьте его в механизм БД, либо (более эффективно) выполните его в PL/pgSQL (или на некотором языке процедурной серверной) динамически с помощью EXECUTE. Подробнее:

Решение

CREATE OR REPLACE FUNCTION f_get_columns(_cols text[])
RETURNS TABLE (col text, val text) AS
$func$
DECLARE
_col text;
BEGIN
FOREACH _col IN ARRAY _cols LOOP
RETURN QUERY EXECUTE
format('SELECT %1$L::text, %1$I::text FROM tbl t', _col);
END LOOP;
END
$func$ LANGUAGE plpgsql;

Вызов:

SELECT * FROM f_array_of_columns('{column1,column2}');

Возвраты (случайные значения):

col     | val
--------+-----
column1 | 001
column1 | 002
column1 | 003
column2 | {foo,boo,foo}
column2 | {"",for,test}
column2 | {test,foo,boo}

Ключевые элементы:

  • Соответствующая декларация RETURNS.
  • Здесь вы можете повторить свои результаты, RETURN QUERY EXECUTE.
  • Цикл FOREACH в данном конкретном случае.
  • format() для упрощения конкатенации строк и эвакуационных имен и значений.
    Обратите внимание на спецификаторы:
    %1$L… первый параметр как цитируемый литерал.
    %1$I… первый параметр как правильно экранированный идентификатор.

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

Ответ №2

Точно, мне нужен динамический SQL, но мне не нужно его обрабатывать с пользовательского ввода, динамический SQL будет построен из массива, где хранятся имена столбцов, значение в столбцах, которые я должен хранить в переменной, что-то вроде:

CREATE OR REPLACE FUNCTION test()
RETURNS integer AS
$func$
DECLARE
ok integer := 0;
cols varchar[] := array['col1','col2','col3','col4','col5'];
_row record;
BEGIN

FOR i IN 1 .. array_length(cols, 1)
LOOP

-- I wanna know how to make a dynamic sql for this purpose
select t.cols[i] into _row -- for cols[1] this would build a sql like, "select.col1 into _row from table t"
from table t;

insert into x values (_row); -- then use that variable "_row" and insert in another table

END LOOP;

return ok;
END
$func$ LANGUAGE plpgsql;

Еще один совет: я использую PostgreSQL 8.4, поэтому я не могу использовать инструкцию FOREACH

Оцените статью
TechArks.Ru
Добавить комментарий