web-dev-qa-db-ja.com

カーソルでAS400テーブルをループする方法

1人あたり複数の行を含むAS400テーブルがあります。各行には、各トランザクションに割り当てられたポイントを含む、個人によるトランザクションに関するデータが含まれています。ポイントで注文された1人のすべての行を読みました。最も高いポイントの最初の列、私は一人にしておく。後続の行では、ポイント値が半分にカットされ、更新を行います。現在、カーソルを使用してテーブルを開き、ループを実行して行を読み取ります。 -508エラーの説明:

WHERE CURRENT OF CLを指定したUPDATEまたはDELETEステートメントが試行されましたが、カーソルが行に配置されていないか、行に配置されていますが、COMMIT HOLDまたはROLLBACK HOLDステートメントが行のロックを解放したため、行はロックされていません。カーソルを行に配置して行をロックするには、FETCHステートメントを発行する必要があります。回復。 。 。 :FETCHステートメントを発行して、カーソルを行に配置し、行をロックします。その後、要求を再試行してください。

私のコードの一部は以下の通りです:

DECLARE V_LNAME CHAR ( 30 ) ; 
DECLARE V_LNAMEHOLD CHAR ( 30 ) ; 
DECLARE V_FNAME CHAR ( 15 ) ; 
DECLARE V_FNAMEHOLD CHAR ( 15 ) ; 
DECLARE V_DOB DATE ; 
DECLARE V_DOBHOLD DATE ; 
DECLARE V_TRANSNMBR CHAR ( 9 ) ; 
DECLARE V_TRANSNMBRHOLD CHAR ( 9 ) ; 
DECLARE V_POINTS NUMERIC ( 5 ) ; 
DECLARE V_POINTSHOLD NUMERIC ( 5 ) ; 
DECLARE V_POINTSEQ NUMERIC ( 5 ) ; 
DECLARE FIRSTRECORD CHAR ( 1 ) ; 
DECLARE CL CURSOR FOR 
SELECT LNAME , FNAME , DOB , TRANSNCNMBR , TOPOINTS 
FROM DB_TRANSDATA 
ORDER BY LNAME ASC , FNAME ASC , DOB ASC , TOPOINTS DESC ; 
DECLARE CLHLD CURSOR FOR 
SELECT LNAME , FNAME , DOB , TRANSNCNMBR , TOPOINTS 
FROM DB_TRANSDATA 
ORDER BY LNAME ASC , FNAME ASC , DOB ASC , TOPOINTS DESC ; 

OPEN CLHLD ; 
FETCH CLHLD INTO V_LNAMEHOLD , V_FNAMEHOLD , V_DOBHOLD , V_TRANSNMBRHOLD ; 
close clhld;

OPEN CL ; 
SET FIRSTRECORD = 'Y' ; 
LOOP 
FETCH CL INTO V_LNAME , V_FNAME , V_DOB , V_TRANSNMBR , V_POINTS , V_POINTSEQ ; 
IF TRIM ( CHAR ( V_LNAME ) ) = TRIM ( CHAR ( V_LNAMEHOLD ) ) AND TRIM ( CHAR ( V_FNAME ) ) = TRIM ( CHAR ( V_FNAMEHOLD ) ) AND V_DOB = V_DOBHOLD AND V_TRANSNMBR = V_TRANSNMBRHOLD AND FIRSTRECORD = 'N' THEN 
SET V_POINTSEQ = V_POINTS * .5 ; 

UPDATE DB_TRANSDATA 
SET POINTSEQ = V_POINTSEQ 
WHERE CURRENT OF CL ; 

SET V_LNAMEHOLD = V_LNAME ; 
SET V_FNAMEHOLD = V_FNAME ; 
SET V_DOBHOLD = V_DOB ; 
SET V_TRANSNMBRHOLD = V_TRANSNMBR ; 
ELSE 

UPDATE DB_TRANSDATA 
SET POINTSEQ = V_POINTS 
WHERE CURRENT OF CL ; 

SET V_LNAMEHOLD = V_LNAME ; 
SET V_FNAMEHOLD = V_FNAME ; 
SET V_DOBHOLD = V_DOB ; 
SET V_TRANSNMBRHOLD = V_TRANSNMBR ; 
SET FIRSTRECORD = 'N' ; 
END IF ; 

END LOOP ; 

CLOSE CL;


END  ; 
2
Lele

カーソルの終了条件をチェックしていません。

DECLARE END_CL INT DEFAULT 0;
DECLARE CL CURSOR FOR 
SELECT LNAME , FNAME , DOB , TRANSNCNMBR , TOPOINTS 
FROM DB_TRANSDATA 
ORDER BY LNAME ASC , FNAME ASC , DOB ASC , TOPOINTS DESC ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET END_CL = 1;
FETCH CL INTO V_LNAME , V_FNAME , V_DOB , V_TRANSNMBR , V_POINTS , V_POINTSEQ ;
WHILE END_CL = 0 DO
    . . .
    FETCH CL INTO V_LNAME , V_FNAME , V_DOB , V_TRANSNMBR , V_POINTS , V_POINTSEQ ; 
END WHILE;

詳細については:

IBM i 7.1インフォメーションセンター > データベース > プログラミング > SQLプログラミング > ルーチン > ストアドプロシージャ

IBM Redbooks > Power Systems > DB2 Universal Database™for iSeriesのストアドプロシージャ、トリガー、およびユーザー定義関数

4
jamesallman