如何从Postgres中的选择查询的数组中获取列名

时间:2014-07-22 15:55:16

标签: arrays function postgresql plpgsql dynamic-sql

我需要查询一个表,从数组中获取列名... 像这样的东西

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

你明白了吗?有可能吗?

2 个答案:

答案 0 :(得分:1)

每当您需要在SQL语句中将用户输入转换为identifierscode时,您需要动态SQL 。要么在客户端中连接语句,要么将其发送到数据库引擎,要么(更有效地)使用EXECUTE动态地在PL / pgSQL(或某些过程服务器端语言)中进行。更多细节:

解决方案

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)以匹配返回类型,并使其适用于任何数据类型。根据具体要求,这可能更具体。

答案 1 :(得分:0)

确实,我需要动态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语句