La chose à garder à l'esprit est que l'instruction DECLARE
est et non exécutable. C'est une déclaration de compilation. PREPARE
et OPEN
sont exécutables. Ci-dessous est un programme entièrement fonctionnel qui utilise SQL dynamique, notez que le sous-programme DeclareCursor
n'est jamais réellement appelé. Ce qui compte, c'est l'instruction, dans gSqlStmt, au moment où l'instruction PREPARE
est exécutée.
**FREE
ctl-opt main(mymain);
ctl-opt option(*srcstmt);
dcl-c QUOTE const('''');
dcl-s gSqlStmt varchar(500);
dcl-proc MyMain;
dcl-s company char(3);
dcl-s part char(25);
dcl-s desc char(30);
dcl-s msg char(50);
dcl-s selComp char(3);
selComp = 'A06';
gSqlStmt = 'select pmco#, pmpart, pmdesc'
+ ' from pdpmast'
+ ' where pmco# = ' + QUOTE + selComp + QUOTE;
exsr OpenCursor;
exsr FetchData;
exec SQL close C1;
selComp = 'A15';
gSqlStmt = 'select pmco#, pmpart, pmdesc'
+ ' from pdpmast'
+ ' where pmco# = ' + QUOTE + selComp + QUOTE;
exsr OpenCursor;
exsr FetchData;
exec SQL close C1;
*INLR = *ON;
return;
begsr DeclareCursor;
exec SQL
declare C1 cursor for S1;
endsr;
begsr OpenCursor;
exec SQL prepare S1 from :gSqlStmt;
exec SQL open C1;
endsr;
begsr FetchData;
exec sql fetch next from C1 into :company, :part, :desc;
msg = company + ':' + part + ':' + %subst(desc:1:20);
dsply msg;
endsr;
end-proc;
En plus de ne pas avoir le traitement des erreurs, le ci-dessus contient la mauvaise pratique de concaténer directement une variable d'entrée, selComp, dans une déclaration. Ce n'est pas une bonne idée dans n'importe quelle langue en raison d'attaques par injection SQL.
Une meilleure version utilisant des marqueurs de paramètres est présentée ci-dessous. Notez que l'instruction n'a pas besoin de changer plus longtemps. Donc j'ai juste besoin de le préparer une fois. La sélection d'enregistrement dépend de la valeur de selComp au moment où l'instruction OPEN ... USING...
est appelée.
**FREE
ctl-opt main(mymain);
ctl-opt option(*srcstmt);
dcl-s gSqlStmt varchar(500);
dcl-proc MyMain;
dcl-s company char(3);
dcl-s part char(25);
dcl-s desc char(30);
dcl-s msg char(50);
dcl-s selComp char(3);
gSqlStmt = 'select pmco#, pmpart, pmdesc'
+ ' from pdpmast'
+ ' where pmco# = ?';
exec SQL prepare S1 from :gSqlStmt;
selComp = 'A06';
exsr OpenCursor;
exsr FetchData;
exec SQL close C1;
selComp = 'A15';
exsr OpenCursor;
exsr FetchData;
exec SQL close C1;
*INLR = *ON;
return;
begsr DeclareCursor;
exec SQL
declare C1 cursor for S1;
endsr;
begsr OpenCursor;
exec SQL open C1 using :selComp;
endsr;
begsr FetchData;
exec sql fetch next from C1 into :company, :part, :desc;
msg = company + ':' + part + ':' + desc;
dsply msg;
endsr;
end-proc;
Cependant, SQL dynamique n'est pas réellement nécessaire ici. Une instruction statique avec une variable hôte fonctionnera très bien. Avec le SQL statique, je n'ai pas besoin de PREPARE
quoi que ce soit, ni de spécifier selComp sur le OPEN
. Tout cela est fait automatiquement au moment de la compilation.
**FREE
ctl-opt main(mymain);
ctl-opt option(*srcstmt);
dcl-s gSqlStmt varchar(500);
dcl-proc MyMain;
dcl-s company char(3);
dcl-s part char(25);
dcl-s desc char(30);
dcl-s msg char(50);
dcl-s selComp char(3);
selComp = 'A06';
exsr OpenCursor;
exsr FetchData;
exec SQL close C1;
selComp = 'A15';
exsr OpenCursor;
exsr FetchData;
exec SQL close C1;
*INLR = *ON;
return;
begsr DeclareCursor;
exec SQL
declare C1 cursor for
select pmco#, pmpart, pmdesc
from pdpmast
where pmco# = :selComp;
endsr;
begsr OpenCursor;
exec SQL open C1;
endsr;
begsr FetchData;
exec sql fetch next from C1 into :company, :part, :desc;
msg = company + ':' + part + ':' + desc;
dsply msg;
endsr;
end-proc;
montrez votre code ou au moins quelques exemples de ce que vous essayez de faire.Comment voulez-vous que l'instruction change entre les courses? Quels messages d'erreur obtenez-vous? – Charles
La publication génère une déclaration SQL à la volée. Puis l'exécute. Je peux voir que la clause de l'ordre change tout de suite. – danny117