web-dev-qa-db-fra.com

Comment boucle à travers la table AS400 avec curseur

J'ai une table AS400 qui contient plusieurs rangées par personne. Chaque ligne contient des données concernant une transaction de la personne, y compris des points attribués à chaque transaction. J'ai lu toutes les lignes pour une personne commandée par les points. La première rangée avec les plus hauts points, je pars seul. Sur les lignes suivantes, les valeurs de points sont coupées en deux et je fais une mise à jour. J'utilise actuellement un curseur pour ouvrir la table et faire une boucle pour lire les rangées. Je reçois un -508 erreur indiquant:

Une instruction de mise à jour ou de suppression avec un courant de CL a été tentée, mais le curseur n'est pas positionné sur une rangée ou est positionné sur une rangée, mais la ligne n'est pas verrouillée car une instruction de retenue de validation ou de rollback a publié le verrouillage de la rangée. . Une instruction de récupération doit être émise pour positionner le curseur sur une rangée et verrouille la ligne. Récupération . . . : Émettez une instruction de récupération pour positionner le curseur sur une ligne et verrouillez la ligne; Ensuite, essayez à nouveau la demande.

Une partie de mon code est ci-dessous:

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

Vous ne vérifiez pas une fin de condition du curseur.

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;

Pour plus d'informations:

Centre d'information IBM I 7.1 > base de données > programmation > programmation SQL > routines > Procédures stockées

IBM Redbooks > Systèmes d'alimentation > procédures stockées, déclencheurs et fonctions définies par l'utilisateur sur DB2 Universal Database ™ pour iSeries

4
jamesallman