RXSQL

RXSQL

Az RXSQL segítségével REXX programokból közvetlenül használhatjuk a DB/2-t szabványos SQL hívásokkal.

Természetesen az RXSQL használatához szükséges a REXX és az SQL előzetes ismerete.

Alapelvek

Cursor

A leggyakoribb SQL parancs a SELECT. Problémát okoz, hogy előre nem megbecsülhető az eredmény mérete. Ezt többféle módon lehet lekezelni, ezek közül a legelterjedtebb módot használja az RXSQL, melynek során úgynevezett cursor-okat használunk. Ilyenkor egy parancs (legalább) 3 részből áll:

Dynamic SQL

A DB/2 3 féle módon képes végrehajtani az utasításokat:

Programozási ismeretek

A programon belül az RXSQL utasításokat (szimpla vagy dupla) idézőjelek közé kell írni. Ha a parancson belük akarunk idézőjelet használni, akkor a másik fajtát használjuk, pl.:
                                                                        
"RXSQL PREPARE a UPDATE uu98.alap SET all_eretev=1990 ",                        
"WHERE alp_nev='Józsi'"                                                         
Ha nem fér egy sorba az utasítás, akkor a következőben folytathatjuk, csak egy vesszőt kell tenni a sor végére.

Az RXSQL parancsok első szava kötelezően RXSQL vagy EXECSQL. A fő különbség köztük, hogy az EXECSQL hibakezelését továbbfejlesztették.

Az RXSQL-ben az azonosítók első karaktere betű (A-Z,a-z), vagy szimbólum ($,#,@); a további karakterek között szám és aláhúzás is szerepelhet.

Paraméterátadás

Jellemzően nem csak egy változót adunk át egy SQL híváskor, hanem többet. Ezt kétféle módon tehetjük meg:

Típusok

INTEGER : egész
  • SMALLINT : rövid egész
  • REAL : valós, egyszeres pontosságú
  • FLOAT : valós, kétszeres pontosságú
  • DECIMAL(m,n) : fixpontos, m jegyű, n tizesessel
  • CHAR(n) : szöveges
  • DATATIME-mot a megfelelő hosszú CHAR(n) segítségével használhatunk
  • VARCHAR(n) : változó (max n) hosszú szöveges
  • LVARCHAR(n) : változó (max n) hosszú szöveges
  • GRAPHIC(n) : bináris sztring
  • VARGRAPHIC(n) : változó (max n) hosszú bináris sztring
  • LVARGRAPHIC(n) : változó (max n) hosszú bináris sztring

    Hibakezelés

    Számos változó tartalmaz hibakezelési információkat (pl.: SQLSTATE, SQLERRM, SQLERRP, SQLWARN, SQLERRD.n)m de a leglényegesebb az SQLCODE, és az RC ez utóbbi értéke változik a hívás módjától:
    • EXECSQL :
      • 0 : normál (nincs hiba)
      • 10 : figyelmeztetés (pl, ha SQLCODE=100: utolsó elemhez értünk a FETCH-nél)
      • -10 : hiba
      • >1000 : figyelmeztetés, RXSQLMSG
      • <-100 : hiba, RXSQLMSG
      • -3,28,41 : CMS hiba
    • RXSQL :
      • 0 : normál (nincs hiba)
      • 4 : figyelmeztetés (pl, ha SQLCODE=100: utolsó elemhez értünk a FETCH-nél)
      • 8 : hiba
      • >100 : hiba, RXSQLMSG
      • -3,28,41 : CMS hiba
    RXSQLMSG szöveges hibaüzenetet tartalmaz a jelzett esetekben.

    Fontosabb utasítások

                                                                            
    PREP[ARE] nev sqlparancs|valtozo                                                
    
    Segítségével előkészíthetünk egy utasítást. A nev tetszőleges, ehhez rendelődik az előkészített utasítás, amelyet vagy közvetlenül adunk meg, vagy pedig a valtozo-ban van.
                                                                            
    OPEN nev                                                                        
    
    Megnyitja a nev-hez tartozó cursort illetve a nev-hez tartozó előkészített utasítást. Ezután lehet pl. FETCH-elni, a cursort az első elé állítja.
                                                                            
    FETCH nev [INTO] valtozolista|stemvaltozo                                       
    
    A FETCH segíségével lehet egy megnyitott SELECT eredményének következő sorát berakni változókba.
                                                                            
    CLOSE nev                                                                       
    
    Lezárja a megnyitott cursort.
                                                                            
    COMMIT [WORK] [RELEASE]                                                         
    
    A tranzakciót lezárja. Ekkor kerül bele a tényleges változtatás az adatbázisba. A WORK csak dísz, RELEASE esetén lezárja a kapcsolatot az adatbázissal.
                                                                            
    ROLLBACK [WORK] [RELEASE]                                                       
    
    A tranzakciót érvényteleníti. Minden, a tranzakció közben történt módosítást visszacsinál. A WORK csak dísz, RELEASE esetén lezárja a kapcsolatot az adatbázissal.
                                                                            
    PURGE *|cursor|utasítás                                                         
    
    Megszünteti a megadott ideiglenesen eltárolt cursort/utasítást (több is megadható), illetve az összeset (* esetén).

    RXSQL példprogramok

                                                                               
                                                                                    
    /*Csupa nagybetus nevuek keresese*/                                             
    say ' csupa nagybetus nevuek keresese'                                          
                                                                                    
    next.a='A'                                                                      
    nagyok=0                                                                        
    oid=0                                                                           
    say ' ' date('O')                                                               
                                                                                    
    sel_emp = 'SELECT alp_id, alp_rogznev, alp_nev,alp_rogzdatum,                   
    alp_contnev, alp_contdat FROM uu98.alap where alp_lastupd ',                    
    "> timestamp('1998-01-01-00.00.00.0000') order by alp_id"                       
    /*03-30-a kov*/                                                                 
    'RXSQL PREP SELEMP' sel_emp /* Prepare the SELECT statement */                  
    if rc <> 0 & rc <> 4 then signal 'ERROR'                                        
    'RXSQL OPEN SELEMP'        /* Open the SELECT statement */                      
    if rc<>0 then signal 'ERROR'                                                    
                                                                                    
    If rc = 0 then Do           /* If no errors occurred then */                    
       j='A'                                                                        
    say '   id      név                   rögzítő:neve,dátum  kontroll:neve,dátum'  
       say ' ---------------------------------------------------------------'       
       Do Forever               /*   Get data from the table */                     
                                                                                    
          /* Get the data into REXX variables from DB2 for VM */                    
          'RXSQL FETCH SELEMP ALP_ID ALP_ROGZNEV ALP_NEV ALP_ROGZDATUM,             
           ALP_CONTNEV, ALP_CONTDAT'                                                
          If (rc = 4 & SQLCODE = 100)  then Leave  /* If there is no more */        
          Else If rc <> 0 then Signal 'ERROR'     /* If there is an error */        
                                                                                    
          /* Check for Nulls */                                                     
         if ALP_ID        = 'ALP_ID' then ALP_ID        = ''                        
         if ALP_ROGZNEV   = 'ALP_ROGZNEV' then ALP_ROGZNEV   = ''                   
         if ALP_CONTNEV   = 'ALP_CONTNEV' then ALP_CONTNEV   = ''                   
         if ALP_CONTDAT   = 'ALP_CONTDAT' then ALP_CONTDAT   = ''                   
         if ALP_ROGZDATUM = 'ALP_ROGZDATUM' then ALP_ROGZDATUM = ''                 
         if ALP_NEV   = 'ALP_NEV' then ALP_NEV   = ''                               
                                                                                    
         ALP_NEV2=ALP_NEV                                                           
         upper ALP_NEV2                                                             
         if ALP_NEV2=ALP_NEV then do                                                
          if ((ALP_ID  ) %  200) <> ((oid  ) %  200) then say '  '                  
          nagyok=nagyok+1                                                           
          say ' ' left(nagyok,4) left(ALP_ID,6)  left(ALP_NEV,20),                  
          left(ALP_ROGZNEV,8) left(ALP_ROGZDATUM,10)    left(ALP_CONTNEV,8),        
          left(ALP_CONTDAT,10)                                                      
          say '+' left(' ',4) left(ALP_ID,6)                                        
          oid=ALP_ID                                                                
         end                                                                        
       End                                                                          
       'RXSQL CLOSE SELEMP'    /* Close the SELECT statement */                     
       if rc<>0 then signal 'ERROR'                                                 
       say ' ==============================================================='       
       say '1'                                                                      
    End                                                                             
    'RXSQL COMMIT'              /* Commit the transaction */                        
    'RXSQL PURGE SELEMP'       /* Purge Preped statement */                         
    vege:                                                                           
    mezo=''                                                                         
    ertek=''                                                                        
    rel=''                                                                          
                                                                                    
    ERROR:      /* A fatal error occurred  */                                       
                /* Forget all inserted data so far */                               
    errrc = rc                                                                      
    If errrc >= 100 then Do                                                         
       Say '  RXSQL Error:' errrc rxsqlmsg                                          
       'RXSQL ROLLBACK'                                                             
    End                                                                             
    Else If errrc = 4 ! errrc = 8 then Do                                           
       Say '  Sqlcode:' sqlcode                                                     
       Say ' Sqlstate:' sqlstate                                                    
       Do errd = 1 to 6                                                             
          If sqlerrd.errd <> 0 then Say '  Sqlerrd.'errd':' sqlerrd.errd            
                                                                                    
       End                                                                          
       If sqlerrp <> '' then Say '  Sqlerrp:' sqlerrp                               
       If sqlerrm <> '' then Say '  Sqlerrm:' sqlerrm                               
       If sqlwarn <> '' then Say '  Sqlwarn:' "'"sqlwarn"'"                         
       If sqlcode < 0 & "INDEX"('WS',"SUBSTR"(sqlwarn,7,1)) = 0 then                
          'RXSQL ROLLBACK'                                                          
    End                                                                             
    Exit errrc                                                                      
    

                                                                               
                                                                                    
    /*Nem magyar ekezetesek  keresese*/                                             
    say ' Nem magyar ekezetesek  keresese'                                          
    say ' ' date('O')                                                               
                                                                                    
    next.a='A'                                                                      
    nagyok=0                                                                        
    oid=0                                                                           
    ekezet='éáíóöüőűúÉÁÍÓÖÜŐŰÚ'                                                     
    file='NOHUNCH FELVMEMO A'                                                       
                                                                                    
    sel_emp = 'SELECT alp_id, alp_rogznev, alp_nev,alp_rogzdatum,                   
    alp_contnev, alp_contdat, alp_anev,alp_allut from uu98.alap ',                  
                                           'where alp_lastupd ',                    
    "> timestamp('1998-01-01-00.00.00.0000')"                                       
    'RXSQL PREP SELEMP' sel_emp /* Prepare the SELECT statement */                  
    if rc <> 0 & rc <> 4 then signal 'ERROR'                                        
    'RXSQL OPEN SELEMP'        /* Open the SELECT statement */                      
    if rc<>0 then signal 'ERROR'                                                    
                                                                                    
    If rc = 0 then Do           /* If no errors occurred then */                    
       j='A'                                                                        
       say '    id      név                   rögzítő:neve,dátum  kontroll:neve,dátu
       say ' ---------------------------------------------------------------'       
       Do Forever               /*   Get data from the table */                     
                                                                                    
          /* Get the data into REXX variables from DB2 for VM */                    
          'RXSQL FETCH SELEMP ALP_ID ALP_ROGZNEV ALP_NEV ALP_ROGZDATUM,             
           ALP_CONTNEV, ALP_CONTDAT, ALP_ANEV ALP_ALLUT'                            
          If (rc = 4 & SQLCODE = 100)  then Leave  /* If there is no more */        
          Else If rc <> 0 then Signal 'ERROR'     /* If there is an error */        
                                                                                    
          /* Check for Nulls */                                                     
         if ALP_ID        = 'ALP_ID' then ALP_ID        = ''                        
         if ALP_ROGZNEV   = 'ALP_ROGZNEV' then ALP_ROGZNEV   = ''                   
         if ALP_CONTNEV   = 'ALP_CONTNEV' then ALP_CONTNEV   = ''                   
         if ALP_CONTDAT   = 'ALP_CONTDAT' then ALP_CONTDAT   = ''                   
         if ALP_ROGZDATUM = 'ALP_ROGZDATUM' then ALP_ROGZDATUM = ''                 
         if ALP_NEV   = 'ALP_NEV' then ALP_NEV   = ''                               
         if ALP_ANEV   = 'ALP_ANEV' then ALP_ANEV   = ''                            
         if ALP_ALLUT = 'ALP_ALLUT' then ALP_ALLUT   = ''                           
                                                                                    
         st= ALP_ID !! ALP_NEV !! ALP_ANEV !! ALP_ALLUT                             
         st2=''                                                                     
         parse var ALP_ALLUT st1 st2 .                                              
         if st2<>'' &   verify(st,ekezet,m)=0 then do                               
          if ((ALP_ID  ) %  200) <> ((oid  ) %  200) then say '  '                  
          nagyok=nagyok+1                                                           
          say ' ' left(nagyok,4) left(ALP_ID,6)  left(ALP_NEV,20),                  
          left(ALP_ROGZNEV,8)       left(ALP_ROGZDATUM,10)   ,                      
             left(ALP_CONTNEV,8),                                                   
                left(ALP_CONTDAT,10)                                                
          say '+' left(' ',4) left(ALP_ID,6)                                        
          say '             '  left(ALP_ALLUT,20) left(ALP_ANEV,40)                 
          oid=ALP_ID                                                                
         end                                                                        
       End                                                                          
       'RXSQL CLOSE SELEMP'    /* Close the SELECT statement */                     
       if rc<>0 then signal 'ERROR'                                                 
       say ' ==============================================================='       
       say '1'                                                                      
    End                                                                             
    'RXSQL COMMIT'              /* Commit the transaction */                        
    'RXSQL PURGE SELEMP'       /* Purge Preped statement */                         
    vege:                                                                           
    mezo=''                                                                         
    ertek=''                                                                        
    rel=''                                                                          
                                                                                    
    ERROR:      /* A fatal error occurred  */                                       
                /* Forget all inserted data so far */                               
    errrc = rc                                                                      
    If errrc >= 100 then Do                                                         
       Say '  RXSQL Error:' errrc rxsqlmsg                                          
       'RXSQL ROLLBACK'                                                             
    End                                                                             
    Else If errrc = 4 ! errrc = 8 then Do                                           
       Say '  Sqlcode:' sqlcode                                                     
       Say ' Sqlstate:' sqlstate                                                    
       Do errd = 1 to 6                                                             
          If sqlerrd.errd <> 0 then Say '  Sqlerrd.'errd':' sqlerrd.errd            
                                                                                    
       End                                                                          
       If sqlerrp <> '' then Say '  Sqlerrp:' sqlerrp                               
       If sqlerrm <> '' then Say '  Sqlerrm:' sqlerrm                               
       If sqlwarn <> '' then Say '  Sqlwarn:' "'"sqlwarn"'"                         
       If sqlcode < 0 & "INDEX"('WS',"SUBSTR"(sqlwarn,7,1)) = 0 then                
          'RXSQL ROLLBACK'                                                          
    End                                                                             
    Exit errrc                                                                      
    

    PIPE és SQL kapcsolata

    Az SQLSEL stage parancs segítségével pipe-ból is kiadhatunk SQL hívásokat.
                                                                               
    /* csak k-s jel., de van allami is */                                           
    "pipe sqlsel select jso_alp_id, int_kod, jso_fsorszam, szp_rnev  ",             
    "from uu98.jsorsz j, uu98.jelentk, uu98.szakpar, uu98.fint",                    
    "where jso_koltseg='K' and jso_jel_id=jel_id  and jel_szp_id=szp_id",           
    "and szp_letszam>0 and szp_int_id=int_id and",                                  
    "not exists (select * from uu98.jsorsz j2",                                     
    "where j2.jso_jel_id=j.jso_jel_id and j2.jso_koltseg='A')",                     
    "order by jso_alp_id",                                                          
    "! > bc tmp a"                                                                  
    

                                                                               
                                                                                    
    /*intezmenyenkent mennyi rogzitetlen eredmeny van*/                             
    "pipe sqlsel select ere_int_id, ere_vjelleg, ere_tipus, count(*)",              
    "from uu98.eredm",                                                              
    "where ere_del='A' AND ere_orokit IN ('I', 'N') AND",                           
    "ere_bke_id IS NULL                                               ",            
    "group by ere_int_id, ere_vjelleg, ere_tipus ",                                 
    "! specs 1-34 1 /Ossz:/ NW  35-50 NW ! > Bd1 TMP A"                             
    say 'ossz kesz'                                                                 
    "pipe sqlsel select ere_int_id, ere_vjelleg, ere_tipus, count(*)",              
    "from uu98.eredm",                                                              
    "where ere_del='A' AND ere_orokit IN ('I', 'N') AND",                           
    "ere_bke_id IS NULL AND ere_epont IS NOT NULL                         ",        
    "group by ere_int_id, ere_vjelleg, ere_tipus ",                                 
    "! specs 1-34 1 /Feld:/ NW 35-50 NW ! >> Bd1 TMP A"                             
    say 'ossz kesz'                                                                 
    " pipe < bd1 tmp a ! sort ! > bd tmp a "                                        
    

                                                                               
                                                                                    
    /* behivo intezmenyek  */                                                       
                                                                                    
    "pipe (end ?) sqlsel int_kod, tan_nev, ere_tdatum, count(*)           ",        
    "from uu98.eredm, uu98.ftan, uu98.fint ",                                       
    "where ere_int_id_h=int_id and ere_tan_id=tan_id and ere_del='A'  ",            
    "and ere_orokit in ('I','N') and ere_eretev=0 and ere_vjelleg='K'",             
    "group by int_kod, tan_nev, ere_tdatum !",                                      
    "drop 1 ! spec 1-52 1 /I/ 54 54-* 56 !",                                        
    "> b9 tmp a "                                                                   
                                                                                    
    "pipe sqlsel int_kod, tan_nev, ere_tdatum, count(*)           ",                
    "from uu98.eredm, uu98.ftan, uu98.fint ",                                       
    "where ere_int_id_h=int_id and ere_tan_id=tan_id and ere_del='A'  ",            
    "and ere_orokit in ('I','N') and ere_eretev<>0 and ere_vjelleg='K'",            
    "group by int_kod, tan_nev, ere_tdatum! drop 1 ",                               
    "! spec 1-52 1 /R/ 54 54-* 56 ! >> b9 tmp a"                                    
                                                                                    
                                                                                    
    tab=d2c(5)                                                                      
                                                                                    
    "pipe < b9 tmp a ! sort ! stem s."                                              
    i=1                                                                             
    do s.0                                                                          
      o.i=strip(substr(s.i,1,10)) !! tab !! strip(substr(s.i,12,30))!!,             
       tab !! strip(substr(s.i,43,10)) !! tab !! strip(substr(s.i,54,1))!!,         
       tab !! strip(substr(s.i,56,20))                                              
      i=i+1                                                                         
    end                                                                             
    o.0=s.0                                                                         
    "pipe stem o. ! > b9a tmp a"                                                    
                                                                                    
                                                                                    
                                                                                    
    "felkonv toasc b9a tmp a b9b tmp a"