2013-03-13 3 views
1

Я хотел бы вставить некоторые записи в таблицу во время цикла. Записи передаются в виде вкладки VARCHAR к функции, т.е. .:INSERT while LOOPing

create function a(tab varchar[]) RETURNS void AS 
$$ 
DECLARE 
    b varchar(20); 
BEGIN 
    FOREACH b IN ARRAY tab 
    LOOP 
     INSERT INTO....; 
    END LOOP; 
    RETURN; 
END; 
$$ 
LANGUAGE plpgsql; 

Однако при выполнении есть ошибка:

ERROR: syntax error at or near "FOREACH" 
LINE 1: FOREACH $1 IN ARRAY tab LOOP INSERT INTO x (c, ... 
QUERY: FOREACH $1 IN ARRAY tab LOOP INSERT INTO x (c) VALUES ($1) 
CONTEXT: SQL statement in PL/PgSQL function " near line ... 

********** ERROR ********** 

ERROR: syntax error at or near "FOREACH" 

Кто-нибудь знает, почему и как это исправить?

+0

Какая версия Postgres? «FOREACH IN ARRAY», похоже, был добавлен в 9.1. – NPE

+0

** Всегда ** укажите номер версии, с которой вы работаете. Это сайт программистов, вы должны * знать *, чтобы сделать это. Кроме того, если вы предоставляете полный пример, скорее всего, вам не нужно зацикливаться на всех, и это будет намного быстрее. –

ответ

1

FOREACH конструкция была добавлена ​​в 9.1. Для более ранних версий вы можете использовать unnest() функцию следующим образом:

CREATE FUNCTION a(tab varchar[]) RETURNS void AS 
$$ 
DECLARE 
    b varchar(20); 
BEGIN 
    FOR b IN SELECT unnest(tab) 
    LOOP 
    INSERT INTO x(c) VALUES (b); 
    END LOOP; 
    RETURN; 
END; 
$$ LANGUAGE plpgsql; 
0

Я хочу добавить одну вещь, а именно, что unnest unnests все уровни массива:

select * from unnest(ARRAY[ARRAY[1,2,3],Array[5,6,7]]); 
unnest 
-------- 
     1 
     2 
     3 
     5 
     6 
     7 
(6 rows) 

Если вы хотите, чтобы петля через один уровень многомерного массива, вы должны перебрать следующее вместо

FOR out_count IN 
        array_lower(in_transactions, 1) .. 
        array_upper(in_transactions, 1) 
    LOOP 
     -- Fill the bulk payments table 
     INSERT INTO bulk_payments_in(id, amount) 
     VALUES (in_transactions[out_count][1], 
       in_transactions[out_count][2]); 
    END LOOP; 
+0

PostgreSQL 9.1+ имеет специальную функцию для этого. –

3

с PostgreSQL 9.1 есть также built-in way to loop through array slices:

FOREACH x SLICE 1 IN ARRAY $1 
LOOP 
    RAISE NOTICE 'row = %', x; 
END LOOP; 

Где x должен быть соответствующим массивом типа и ...

The SLICE value must be an integer constant not larger than the number of dimensions of the array

Для 1-мерных массивов просто опустить SLICE части и x может быть простым типом, как вы показываете в вашем вопрос.