Whenever you need to convert user input to identifiers
or code
in an SQL statement, you need dynamic SQL. Either concatenate the statement in your client an send it to the DB engine or (more efficiently) do it in PL/pgSQL (or some procedural server-side language) dynamically with EXECUTE
. More details:
Solution
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;
Call:
SELECT * FROM f_array_of_columns('{column1,column2}');
Returns (random values):
col | val
--------+-----
column1 | 001
column1 | 002
column1 | 003
column2 | {foo,boo,foo}
column2 | {"",for,test}
column2 | {test,foo,boo}
Key elements:
- A matching
RETURNS
declaration.
- A way to ruturn your results,
RETURN QUERY EXECUTE
here.
- A
FOREACH
loop in this particular case.
format()
to simplify string concatenation and escape names and values properly.
Note the specifiers:
%1$L
... first parameter as quoted literal.
%1$I
... first parameter as properly escaped Identifier.
Note how I cast both columns to text
(::text
) to match the return type and make it work for any data type. Depending on exact requirements, this could be more specific.
DO
statement producing notices is the goal? You need to define what you want to return. A set of single values? A set of rows? Arrays? Of what data type exactly? Please edit your question. Do not squeeze essential information into comments. – Erwin Brandstetter Jul 22 '14 at 23:56