Мне нужен запрос таблицы, получающей имя столбца из массива… что-то вроде этого
$$
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;
Ты понял? Является ли это возможным?
Всякий раз, когда вам нужно преобразовать ввод пользователя в 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
), чтобы соответствовать типу возвращаемого значения и заставить его работать для любого типа данных. В зависимости от конкретных требований это может быть более конкретным.
Точно, мне нужен динамический 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