2017-07-19 1 views
-1

Pour commencer, je veux m'excuser pour mon mauvais anglais et il est possible que certaines informations cruciales me manquent.Utiliser le curseur pour plusieurs conditions de recherche

Quoi qu'il en soit. Je développe un fichier d'affichage avec un sous-fichier pour montrer quelques enregistrements. Cela fonctionne comme un charme en montrant un select mais maintenant je veux développer une fonction de recherche pour les utilisateurs. Ainsi, lorsque l'utilisateur entre différentes conditions de recherche, la sélection change et le curseur doit en quelque sorte se mettre à jour avec la nouvelle sélection. Je m'arrache les cheveux, je n'arrive vraiment pas à faire fonctionner ça.

J'ai trouvé un message de "mcpressonine" -forum, il y a un gars qui a exactement le même problème que moi et il a résolu cela mais je ne comprends pas vraiment ce qu'il a fait - sauf de mettre le curseur declare dans un subprocedure que j'ai également fait - sans succès.

Voici un lien vers son forum post: His post

Je serais très reconnaissant si quelqu'un explique ce qu'il a fait. Peut-être que ces solutions ne sont plus valables puisque son poste a maintenant 10 ans. Dites-moi si l'information ne suffit pas et je vais corriger le long du chemin.

Merci! Cordialement, Jesper

+0

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

+0

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

Répondre

0

Vous ne pouvez déclarer un curseur qu'une seule fois dans un programme Embedded-SQL ou dans une procédure stockée. Vous pouvez également déclarer plusieurs curseurs. Mais l'instruction SQL liée à ce curseur peut varier dans le temps.

Le conseil dans la publication visée reste valide. Vous pouvez déclarer le curseur une fois (par exemple dans une procédure stockée), mais l'instruction à laquelle le curseur fait référence peut changer avec le temps tant que ce curseur est fermé (s'il était ouvert) et aussi longtemps que le nouveau SQL- La déclaration est préparée avec succès et le curseur est rouvert, etc.

+0

il reste à voir si l'OP a réellement besoin de SQL dynamique. Selon ce qui change, la statique peut fonctionner. – Charles

1

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;