如何在pgSQL中使用数组循环

时间:2012-08-24 03:03:30

标签: arrays postgresql plpgsql

我想做这样的事情:

CREATE OR REPLACE FUNCTION ff(int, text) RETRUNS integer AS $$
DECLARE
    r text;
BEGIN
    FOR r IN SELECT string_to_array($2, ',')
    LOOP
        INSERT INTO test(i, t) VALUES($1, r);
    END LOOP;
    RETRUN 0;
END
$$LANGUAGE pgsql;

我希望使用SELECT ff(3, 'a,b');这个功能可以做到

INSERT INTO test(i, t) VALUES(3, 'a'); 
INSERT INTO test(i, t) VALUES(3, 'b');

2 个答案:

答案 0 :(得分:10)

自PostgreSQL 9.1以来,您可以使用FOREACH LOOP迭代数组。来自documentation的示例:

CREATE FUNCTION sum(int[]) RETURNS int8 AS $$
DECLARE
  s int8 := 0;
  x int;
BEGIN
  FOREACH x IN ARRAY $1
  LOOP
    s := s + x;
  END LOOP;
  RETURN s;
END;
$$ LANGUAGE plpgsql;

对你来说,mu's answer更好,但是大多数通过标题找到这个问题的用户都会更喜欢我的答案。

答案 1 :(得分:7)

您不需要循环,可以使用unnest将数组从string_to_array转换为一组行,然后使用简单的insert ... select构造:

create or replace function ff(int, text) returns integer as $$
begin
    insert into test(i, t)
    select $1, s 
    from unnest(string_to_array($2, ',')) as dt(s);
    return 0;
end
$$ language plpgsql;

我还纠正了一些拼写错误(RETRUNSRETRUNpgsql)。

您也可以使用regexp_split_to_table

create or replace function ff(int, text) returns integer as $$
begin
    insert into test(i, t)
    select $1, s
    from regexp_split_to_table($2, ',') as dt(s);
    return 0;
end
$$ language plpgsql;

如果你陷入了8.1岁的时代并且对此无能为力,那么也许这样的事情会起作用:

create or replace function ff(int, text) returns integer as $$
declare
    a text[]; 
    i int;
begin
    select string_to_array($2, ',') into a; 
    i := 1;
    loop  
        if i > array_upper(a, 1) then
            exit;
        else
            insert into test(i, t) values($1, a[i]);
            i := i + 1;
        end if;
    end loop;                                 
    return 0;       
end
$$ language plpgsql;

我认为这应该适用于8.1但我无法访问8.1进行检查。