2013-03-13 16 views
5

Quando si lavora con SQL incorporato in RPG, si finisce spesso con un cursore e un ciclo dow per l'elaborazione di tutte le righe nel risultato. La condizione nel ciclo dipende in qualche modo da SQLCOD e/o da SQLSTT, alcune variabili globalmente disponibili in un programma SQLRPGLE?Qual è il modo corretto per verificare la condizione di SQL trovato in ILE RPG?

Ma qual è il modo corretto di verificare questi valori? Alcuni suggeriscono SQLCOD = 0 altri not (SQLCOD = +100 or SQLSTT = '02000'). Uno fallisce su tutti gli avvertimenti, l'altro non fallisce su alcuni errori, quindi non sono contento.

per illustrare ciò che faccio con un certo codice:

Pmain    B 
D     PI 
Dmy_ds   E DS     extname(SOME_TABLE) 
D          qualified 
/free 
    exec sql 
    DECLARE cur CURSOR FOR 
     SELECT * 
     FROM some_table; 
    exec sql 
    OPEN cur; 
    exec sql 
    FETCH cur 
    INTO :my_ds; 
    dow sql_found(); 
     exec sql 
     FETCH cur 
     INTO :my_ds; 
    enddo; 
    exec sql 
    CLOSE cur; 
/end-free 
Pmain    E 


Psql_found  B 
D     PI    N 
/free 
    // insert return statement here... 
/end-free 
Psql_found  E 

Sto cercando l'istruzione return corretto qui, che mi farà passare attraverso tutte le righe se si verifica alcun errore e mi permette di lasciare quando un errore si verifica. Punti bonus per un modo decente di controllare gli errori.

risposta

5

SQLSTATE è migliore e consigliato da IBM.

Da Infocenter di IBM SQL Messages and Codes Reference: SQLCODE and SQLSTATE concepts

SQLSTATE è il codice di ritorno di serie preferita.

SQLSTATE è 5 caratteri, con i primi due byte che identifica un class of conditions.

  • '00' = Qualificato completamento con successo
  • '01' = Attenzione
  • '02' = dati

Tutto il resto è un errore. Solitamente controllo solo per "00".

Semplice. Facile.Più portatile.

L'uso di SQLCODE spesso implica elenchi di codici IMHO inferiori a quelli degli sviluppatori.

Esempio:

Personalmente, io generalmente includono le definizioni e il codice come questo:

D [email protected]  s    * inz(%addr(SQLState)) 
D xSQLState  ds    5 based([email protected]) 
D xSQLState2     2a 
D 
D Success_On_SQL C     const('00') 
D Warning_On_SQL C     const('01') 
D NoData_On_SQL C     const('02') 

Poi, dopo ogni operazione SQL, io in genere controllare

if xSQLState2 <> Success_On_Sql; 
    someflag = true; 
    endif; 
+0

Nota secondaria ... è non completamente vero che "Qualsiasi altra cosa è un errore" per le classi SQLSTATE. Solo le classi riservate per DB2 (e definite come errori) sono necessariamente errori. Segnalare "K1001", ad esempio, sarebbe solo un errore se l'applicazione lo gestisse come un errore. – user2338816

0

ho fatto un po 'di ricerca sul tema e ha trovato something on IBM's site (citazione):

The SQLCODE is also set by the database manager after each SQL 
statement is executed as follows: 
    - If SQLCODE = 0 and SQLWARN0 is blank, execution was successful. 
    - If SQLCODE = 100, no data was found. For example, a FETCH 
    statement returned no data, because the cursor was positioned 
    after the last row of the result table. 
    - If SQLCODE > 0 and not = 100, execution was successful with a 
    warning. 
    - If SQLCODE = 0 and SQLWARN0 = 'W', execution was successful 
    with a warning. 
    - If SQLCODE < 0, execution was not successful. 

Il che mi porterebbe a un sql_found() come questo:

Pfound_sql  B 
D     PI    N 
/free 
    return (SQLCOD >= 0) and (SQLCOD<>100); 
/end-free 
Pfound_sql  E 

che dovrebbe prendere cura della condizione Fine dei dati e esito negativo su tutti gli errori. Non sono sicuro se ci sono alcuni avvertimenti di cui dovrei occuparmi (non voglio rimanere intrappolato in un ciclo infinito, se c'è un avvertimento che porta a non leggere).

+0

1) Mi piacerebbe sconsigliamo l'uso di variabili globali (come SQLCOD) in una sottoprocedura. Cosa succede quando è necessario nidificare un ciclo FETCH all'interno di un altro? Quando il loop interno raggiunge EOF, scatterà inavvertitamente anche l'uscita sul loop esterno. Passa SQLCOD come parametro e quel problema scompare. –

+0

2) Errori di deglutizione (come SQLCOD <> 100) è sconsigliabile. Cosa succede se si tratta di un errore CAST e stai perdendo i dati? –

+0

Un possibile vantaggio di definire una procedura per questo scopo è che si potrebbe forse includere anche la logica generica per gestire errori imprevisti come un CAST, nel caso in cui non si fornisse una logica specifica per gestirli diversamente. Eh? – WarrenT

2

La procedura consigliata consiste nell'elaborare gli SQLCODE previsti (come parte dell'elaborazione prevista) e aggiungere codice di eccezione per gestire quelli che non sono. Un'implementazione:

dow 1=1; // forever 
     exec sql 
     FETCH cur 
     INTO :my_ds; 
    // normal exit   
    if sqlstt = SQL_NODATA; 
    SFLEND = *on;   
    leave;    
    endif;     

    // can't CAST a value 
    if sqlstt = SQL_CAST;   // CAST error        
    ... tell user there's an error and read another 
    iter;                 
    endif;                 

    // decimal data error 
    if sqlstt = SQL_DDE; 
    tell user to call IT and stop reading 
    leave;          
    endif;           


    // whoops! not expected at all. Dump for post-mortem 
    if sqlstt <> SQL_NORMAL;        
    ... tell user to call IT and stop reading 
    dump(a);        
    leave;            
    endif;            

    // test for end of loop 
    // filled subfile page? 
    enddo; // forever 

Con questo tipo di implementazione si deve lasciare intenzionalmente il ciclo; se hai riempito una pagina di subfile, caricato l'elemento più alto in una matrice o hai fatto un errore. Non sono sicuro che esista un'unica implementazione generica che gestirà tutte le circostanze. A volte potresti voler lasciare il ciclo di lettura se hai un blocco di registrazione e talvolta vuoi emettere un messaggio e riprovare (ad esempio).

+1

I nomi che iniziano con SQL sono riservati dal precompilatore. Vedi [Nomi nelle applicazioni RPG ILE che usano SQL] (http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frzajp%2Frzajprpiamco.htm) – WarrenT

Problemi correlati