Join the Stack Overflow Community
Stack Overflow is a community of 6.3 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I need query a table getting the columns name from an array... something like this

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

Did you get it? Is it possible?

share|improve this question
    
Could you include an example of the input and desired output, and explain what happens with your current attempt? – IMSoP Jul 22 '14 at 15:58
    
The output would be the value in the table from the field in the array.. the above function should process something like.. select t.field1 into _row from table t; select t.field2 into _row from table t; select t.field3 into _row from table t; those fields are extracted from the array – Christian Maíz Jul 22 '14 at 16:00
    
Ah, OK, so by "field" you mean "column", and what you're after is to dynamically create the SQL to reference different columns each time round the loop. – IMSoP Jul 22 '14 at 16:38
    
yeah!.. exactly!.. I'll correct.. I'm talking about the column.. How can I select those column from the array? – Christian Maíz Jul 22 '14 at 17:11
    
There is no function header? I don't expect a 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

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.

share|improve this answer

Exactly, I need dynamic SQL, but I don't need to process it from the user input, the dynamic SQL would be built from an array where the columns names are stored, the value in the columns I have to store in a variable , something like:

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, "selec t.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;

Another tip: I'm using PostgreSQL 8.4, so I can't use FOREACH statement

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.