web-dev-qa-db-ja.com

FOREACHと並行して複数のアレイをステップ実行

PL/pgSQLでFOREACHを使用して複数の配列をループすることはできますか?私の場合、同じ次元の3つの配列。次のような要素を渡すにはどうすればよいですか?

for(int i = 0 ; i < array1.length ; i++){
  my_method(array1[i], array2[i], array3[i]);
}

これが私の試みです:

select dugong.session_hugeInsert( 3, '5,2,3,1', '4,3,3,2');
NOTICE:  The transaction is in an uncommitable state.Transaction was rolled back.
NOTICE:  query "SELECT Question_ID, UserResponseID_List, UserResponseList" returned 3 columns 42601
ERROR:  cannot begin/end transactions in PL/pgSQL
HINT:  Use a BEGIN block with an EXCEPTION clause instead.
CONTEXT:  PL/pgSQL function dugong.session_hugeinsert(integer,text,text) line 61 at SQL statement

私の機能:

 CREATE OR REPLACE FUNCTION Dugong.Session_hugeInsert(
    Quiz_ID_ int,       --FK
    QuestionList_ TEXT,
    UserResponseList_ TEXT
)
RETURNS int AS $$
DECLARE
    Session_ID integer;
    QuestionList INT[];
    Question_ID integer;
    QuizQuestionisDone boolean;
    UserResponseList INT[];
    UserResponseID_List INT[];  -- Get from database
    UserResponseID integer;
    tmp int;

BEGIN
    IF EXISTS ( SELECT 1 FROM dugong.quiz WHERE quiz_id = Quiz_ID_ ) THEN

    QuestionList = string_to_array(QuestionList_, ',');
    UserResponseList = string_to_array(UserResponseList_, ',');
    FOREACH UserResponseID in ARRAY UserResponseList
    LOOP
        tmp := Dugong.UserResponse_Add();
        UserResponseID_List :=array_append(UserResponseID_List, tmp );
    END LOOP;  -- Memo: Got UserResponseID_List array

    FOREACH Question_ID, UserResponseID, tmp IN ARRAY Question_ID, UserResponseID_List, UserResponseList
    LOOP
        RAISE NOTICE '%, %, %', QuestionList[i], UserResponseID_List[i], UserResponseList[i] ;
    END LOOP;
    RETURN 200;

    ELSE
        RETURN -1;
    END IF;
END;
$$ LANGUAGE PLPGSQL;

私の最初の解決策はあまり良くないようです:

i:=0; j:=0; k:=0;
FOREACH Question_ID IN ARRAY QuestionList
LOOP
    j := 0;
    FOREACH UserResponseID IN ARRAY UserResponseID_List
    LOOP
        k := 0;
        FOREACH tmp IN ARRAY UserResponseList
            LOOP
        IF (i = j AND j = k) THEN
           RAISE NOTICE '%, %, %', Question_ID, UserResponseID, tmp;
        END IF;
        k := k+1;
            END LOOP;
    j := j+1;
    END LOOP;
i := i + 1;
END LOOP;

適切な方法を教えてください。

4
Sarit

FOREACH単一配列をループするのに非常に便利ですが、をステップ実行することは特に便利ではありません並列の複数の配列。代わりに array_lower()/array_upper() の単純な FOR ループを使用します。

FOR i IN 1 .. array_upper(UserResponseList, 1)
LOOP
   RAISE NOTICE '%, %, %', QuestionList[i], UserResponseID_List[i], UserResponseList[i];
END LOOP;

関数で配列を作成したので、インデックスは1(デフォルト)で始まりますknow。それ以外の場合は、次を使用します。

FOR i IN array_lower(UserResponseList, 1) .. array_upper(UserResponseList, 1)

インデックスiは自動的に定義されます ドキュメント:

変数nameは、タイプintegerとして自動的に定義され、ループ内にのみ存在します。

関連情報と詳細情報:

3