Faire un SELECT INTO dynamique en SQL Embedded sans générer de code retour SQLCODE -312
Objectif :
Il faut parfois écrire nos requêtes SQL EMBEDDED (encapsulées de le code RPGLE) de façon dynamique.
C’est à dire que certaines variables de la requête seront valorisées durant l’exécution du programme et non au moment de son écriture.
C’est très pratique et fonctionne très bien.
Le problème c’est qu’une requête de type SELECT INTO ne fonctionne pas en SQL EMBEDDED dynamique. Elle lève l’erreur SQLCODE -312 dont le texte est le suivant : variable-name IS NOT DEFINED OR NOT USABLE.
Heureusement il existe une solution pour palier à cela : il faut utiliser VALUES ( ) INTO ?.
Exemples :
Requête non dynamique
SELECT OBJECT_COUNT FROM TABLE(QSYS2.LIBRARY_INFO(‘nom_bibliotheque‘));
Retourne bien le nombre d’object contenu dans la bibliothèque nommée ‘nom_bibliotheque‘.
Mais ‘nom_bibliothèque‘ est définie « en dur » et ne variera pas lors de l’exécution.
Pour que la requête porte sur la valeur d’une variable qui sera alimentée lors de l’exécution du programme, il faut utiliser une requête SQL dynamique.
Requête dynamique SELECT INTO : Erreur SQL SQLCODE -312
dcl-s ma_requete char(500) inz;
Dcl-s mon_resultat zoned(5:0) inz;
ma_requete = ‘SELECT OBJECT_COUNT INTO :mon_resultat ‘
+ ‘FROM TABLE(QSYS2.LIBRARY_INFO( »’
+ ma_variable_bibliotheque + »’))’;
EXEC SQL
PREPARE SQLSTM FROM :ma_requete;
if SQLCODE = 0;
EXEC SQL
EXECUTE SQLSTM USING :ma_requete;
endif;
Requête dynamique VALUES () INTO ?
dcl-s ma_requete char(500) inz;
Dcl-s mon_resultat zoned(5:0) inz;
ma_requete = ‘VALUES(‘
+ SELECT OBJECT_COUNT ‘
+ ‘FROM TABLE(QSYS2.LIBRARY_INFO( »’
+ ma_variable_bibliotheque + »’))) INTO ?‘;
EXEC SQL
PREPARE SQLSTM FROM :ma_requete;
if SQLCODE = 0;
EXEC SQL
EXECUTE SQLSTM USING :mon_resultat;
endif;
Cette fois cela fonctionne, la requête retourne bien de nombre d’objets contenus dans la bibliothèque dont le nom est présent dans la variable ma_variable_bibliotheque.
Remarque :
Le PREPARE porte sur la requête : FROM :ma_requete;
Le EXECUTE utilise le champ résultat : USING :mon_resultat;
Requête dynamique VALUES () INTO ? portant sur plusieurs champs
dcl-s ma_requete char(500) inz;
Dcl-s mon_resultat_1 zoned(5:0) inz;
Dcl-s mon_resultat_2 char(20) inz;
ma_requete = ‘VALUES(‘
+ SELECT OBJECT_COUNT, LIBRARY_TYPE ‘
+ ‘FROM TABLE(QSYS2.LIBRARY_INFO( »’
+ ma_variable_bibliotheque + »’))) INTO ?‘;
EXEC SQL
PREPARE SQLSTM FROM :ma_requete;
if SQLCODE = 0;
EXEC SQL
EXECUTE SQLSTM USING :mon_resultat_1, :mon_resultat_2;
endif;