Bonjour,
Après l’exécution d’une instruction SQL préparée en dynamique il est facile de récupérer celle-ci si son exécution a échoué car l’instruction se trouve dans une variable du programme.
Par contre, lorsque cette instruction est statique et que sqlcode < 0 est-il possible de récupérer cette instruction ? Via GET DIAGNOSTICS ?
Bonjour Denis,
Après étude de la page https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_72/db2/rbafzgetdiag.htm , Je dirai que non.
A plus,
Ibmiiste.
Après une petite recherche Internet, il y a ceci :
DSPJOBLOG OUTPUT(*OUTFILE) OUTFILE(QTEMP/ERR_LOG)
Select Qmhmf,
Qmhmid,
Qmhmdt
From Qtemp.Err_Log
Where Qmhsev >= 20
And Substr(Qmhmid, 1, 3) In ('CPA' , 'CPD' , 'CPF' , 'SQL')
Order By Rrn(Err_log) Desc
Fetch First 1 Rows Only
Il vaut donc mieux passer par l’API qui permet de récupérer l’information sans l’écraser (QUSRJOBI) :
rtvJobSQL(JOBI0900:
rcvSize :
'JOBI0900' :
qualfiedJobName :
*blanks :
errAPI :
'0' ) ;
if JOBI0900.lenCurCrs > 0 and JOBI0900.lenCurCrs <= %size(instruction);
instruction = %subst(JOBI0900:JOBI0900.ofsCurCrs + 1:JOBI0900.lenCurCrs);
elseif JOBI0900.lenCurCrs > 0;
instruction = %subst(JOBI0900:JOBI0900.ofsCurCrs + 1);
else;
instruction = 'Dernière instruction SQL indisponible';
endif;
avec :
dcl-ds JOBI0900 likeds(JOBI0900_t);
dcl-ds errAPI likeds(errAPI_t);
dcl-ds qualfiedJobName likeds(qualfiedJobName_t);
dcl-pr rtvJobSQL EXTPGM('QUSRJOBI');
receiver char(65535) options(*varsize); // Receiver variable
rcvLen int(10:0) const; // Length of receiver
fmtName char(8) const; // Format name
qualJobName char(26) const; // qualified job name
internalJobID char(16) const; // Internal Job Id
errAPI likeds(errAPI_t); // Error Code
ResetPfrStat char(1) const; // reset performance statistics
end-pr;
// JOBI0900 Format pour API QUSRJOBI
dcl-ds JOBI0900_t len(65535) qualified template;
nbrBytesRtn int(10:0);
nbrBytesAvl int(10:0);
jobName char(10);
usrName char(10);
jobNbr char(6);
internalJobID char(16);
jobSts char(10);
jobType char(1);
jobSubType char(1);
svrMode char(1);
rsvd char(1);
ofsOpnCrs int(10:0);
sizOpnCrs int(10:0);
nbrOpnCrs int(10:0);
ofsCurCrs int(10:0);
lenCurCrs int(10:0);
stsCurCrs int(10:0);
cCSIDCurCrs int(10:0);
rDBname char(18);
sQLObj char(10);
sQLLib char(10);
sQLObjType char(10);
rsvd2 char(4);
cumNbrFullOpn int(20:0);
cumNbrPsedOpn int(20:0);
ofsCurSQL int(10:0);
lenCurSQL int(10:0);
end-ds;
// Nom qualifié de travail / qualified job name pour utilisation dans les API
dcl-ds qualfiedJobName_t len(26) qualified template;
jobName char(10);
userName char(10);
jobNumber char(6);
end-ds;
La variable « instruction » contient bien l’instruction souhaitée car l’appel à l’API ne contenant pas de SQL ne l’a pas écrasée.
A noter que l’ont peut récupérer plein d’autres informations sur le travail demandé par les 2 méthodes.
Sources : https://blog.xuite.net/vengoal/as400?p=6
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/apis/qusrjobi.htm
Bonsoir,
après recherche, il y a 2 solutions mais pas avec GET DIAGNOSTICS.
La première consiste à utiliser la fonction table QSYS2.GET_JOB_INFO :
SELECT V_SQL_STATEMENT_TEXT
FROM TABLE (
QSYS2.GET_JOB_INFO('338961/QUSER/QZDASOINIT')
);
Le problème c’est que si l’on exécute cette requête pour un autre travail que le travail en cours, on risque fort que d’autres instructions SQL aient été exécutées entre temps, or on veut obtenir l’instruction qui était en erreur alors que seule la dernière est conservée.
Si on l’exécute pour son propre travail (par un appel à une procédure juste après l’erreur), on obtient cette instruction qui est en fait la dernière car elle a écrasé la précédente, dans la colonne V_SQL_STATEMENT_TEXT :
SELECT V_SQL_STATEMENT_TEXT
FROM TABLE (
QSYS2.GET_JOB_INFO('*')
);
donne :
"SELECT V_SQL_STATEMENT_TEXT
FROM TABLE (
QSYS2.GET_JOB_INFO(?)
)"
Il vaut donc mieux passer par l’API qui permet de récupérer l’information sans l’écraser (QUSRJOBI) :
rtvJobSQL(JOBI0900:
rcvSize :
'JOBI0900' :
qualfiedJobName :
*blanks :
errAPI :
'0' ) ;
if JOBI0900.lenCurCrs > 0 and JOBI0900.lenCurCrs <= %size(instruction);
instruction = %subst(JOBI0900:JOBI0900.ofsCurCrs + 1:JOBI0900.lenCurCrs);
elseif JOBI0900.lenCurCrs > 0;
instruction = %subst(JOBI0900:JOBI0900.ofsCurCrs + 1);
else;
instruction = 'Dernière instruction SQL indisponible';
endif;
avec :
dcl-ds JOBI0900 likeds(JOBI0900_t);
dcl-ds errAPI likeds(errAPI_t);
dcl-ds qualfiedJobName likeds(qualfiedJobName_t);
dcl-pr rtvJobSQL EXTPGM('QUSRJOBI');
receiver char(65535) options(*varsize); // Receiver variable
rcvLen int(10:0) const; // Length of receiver
fmtName char(8) const; // Format name
qualJobName char(26) const; // qualified job name
internalJobID char(16) const; // Internal Job Id
errAPI likeds(errAPI_t); // Error Code
ResetPfrStat char(1) const; // reset performance statistics
end-pr;
// JOBI0900 Format pour API QUSRJOBI
dcl-ds JOBI0900_t len(65535) qualified template;
nbrBytesRtn int(10:0);
nbrBytesAvl int(10:0);
jobName char(10);
usrName char(10);
jobNbr char(6);
internalJobID char(16);
jobSts char(10);
jobType char(1);
jobSubType char(1);
svrMode char(1);
rsvd char(1);
ofsOpnCrs int(10:0);
sizOpnCrs int(10:0);
nbrOpnCrs int(10:0);
ofsCurCrs int(10:0);
lenCurCrs int(10:0);
stsCurCrs int(10:0);
cCSIDCurCrs int(10:0);
rDBname char(18);
sQLObj char(10);
sQLLib char(10);
sQLObjType char(10);
rsvd2 char(4);
cumNbrFullOpn int(20:0);
cumNbrPsedOpn int(20:0);
ofsCurSQL int(10:0);
lenCurSQL int(10:0);
end-ds;
// Nom qualifié de travail / qualified job name pour utilisation dans les API
dcl-ds qualfiedJobName_t len(26) qualified template;
jobName char(10);
userName char(10);
jobNumber char(6);
end-ds;
La variable « instruction » contient bien l’instruction souhaitée car l’appel à l’API ne contenant pas de SQL ne l’a pas écrasée.
A noter que l’ont peut récupérer plein d’autres informations sur le travail demandé par les 2 méthodes.
Sources : https://blog.xuite.net/vengoal/as400?p=6
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/apis/qusrjobi.htm