lunes, 6 de mayo de 2013

Fetch Relative

Esta es una de las posibilidades que incluye la instrucción SQL Fetch y que utilizo muy habitualmente para acceder a la base de datos ya que es capaz de proporcionar un número de registros a partir de uno determinado sobre una sentencia SQL.

Instrucción

La utilizo de la siguiente manera dentro de un cursor:


Exec SQL  Fetch RELATIVE :WRegInicial FROM KCursor            
                FOR :WRegCargar ROWS into :WArrayDatos;


Permite:
  • Cargar un número determinado de registros. Indica que desde el registro X debe cargar N registros. X se refiere al número inicial según la secuencia de ordenación de la SQL ejecutada, es decir, el número relativo PERO de la ejecución de la instrucción SQL correspondiente. N indica el número MÁXIMO de registros que se quiere que recupere.
    Puede ser muy útil en una estrategia de presentación de carga por páginas.
  • Cargar los datos directamente en un array sin tener que leer el cursor. Ahorra todo el procesamiento y recorrido del cursor. 
Se le indica:
  • Número del registro inicial desde donde comenzará a cargar (WRegInicial). 
  • Número de registros a cargar (WRegCargar)
  • Un array de n registros y con la estructura de datos con los mismos campos que se han incluido en la select (WArrayDatos). Si NO hubiera tantos registros como los solicitados, NO se produce ningún error sino que solo carga en el array los registros que tuviera. Lógicamente NO se pueden cargar más datos que la dimensión que tenga el array.
Por ejemplo, si se quiere cargar en el array los registros de la cuarta página y cada página tiene diez registros, los valores serían los siguientes:
  • WRegInicial=41 (la cuarta página sería 4*10(reg.por pagina)+1)
  • WRegCargar=10  (número de registros a cargar)

Código completo para el uso

Se define el array (P_DatosClie) con la estructura de los campos (Ds_BasClie) con los mismos campos que tendrá la select. Como el array permite 99 entradas, será ese el número máximo de registros que podremos cargar.



     DDs_BasClie       DS                  QUALIFIED    
     D IdCliente                     10  0
     D Nombre                        50
     D Apellidos                     50
     D Direccion                     50


     D P_DatosClie     DS                  Dim(99) LikeDs(Ds_BasClie)

Se define la instrucción SQL en tiempo de ejecución (!lo que podría permitir cambiar el contenido de la clausula WHERE o de ORDER según una selección que hubiera hecho un usuario!).
También se calcula el número del registro inicial (
WRegIni) desde donde comenzará la carga del array. Se basa en dos variables; (WPag) que contiene el número de página solicitada y (WRegCarPag) que contiene el número de registros a cargar por página (máximo 99 ya que así estaba definido el array)


         SentenciaSQL   ='SELECT '                                    +
                         ' a.IdCliente, '                             +
                         ' a.Nombre, '                                +
                         ' a.Apellidos, '                             +
                         ' a.Direccion, '                             +
                        ' FROM '                                      +   
                         ' Cliente a '                                +                                                                    
                        ' ORDER BY '                                  +
                         ' a.IdCliente, '                             ;

          // Calculo del registro inicial segun paginacion
         WRegIni = ((WPag - 1) * WRegCarPag) + 1;



Se define la sentencia y el cursor y se ejecuta el Fetch para cargar el array



// Se declara el cursor                                 
Exec SQL  Declare SClie STATEMENT;                     
Exec SQL  Declare KClie SCROLL cursor for SClie;       
Exec SQL  Prepare SClie FROM :SentenciaSql;            
Exec SQL  Open KClie;                                  
                                                        
// Se recuperan todos los datos                        
Exec SQL  Fetch RELATIVE :WRegIni FROM KClie           
                FOR :WRegCarPag ROWS into :P_DatosClie;
If SqlCod < *Zeros;                                     
  P_NumReg = *Zeros;                                   
Else;                                                  
  P_NumReg = SQLerrd(3);                               
EndIf;                                                 
                                                        
// Se cierra el cursor                                 
Exec SQL  Close KClie;                                  


Después de la ejecución y habiendo comprobado que la ejecución es correcta, en la variable (SQLerrd(3)) tendremos el número de registros que ha cargado en el array. Serán los solicitados en (WRegCarPag) o los que haya podido cargar si ya no quedaban tantos.

Posteriormente podríamos tratar los datos del array como P_DatosClien(1).IdClienteP_DatosClien(3).Nombre, etc.

Forma de uso

Personalmente, encapsulo en un componente este acceso a la base de datos y lo dejo disponible en un programa de servicio (así puedo preparar un separación de capas en el desarrollo). Este componente tendrá:
  • Parámetros de salida
    • Devuelve un array con los datos de la SQL ejecutada
    • Devuelve el número de registros que ha cargado en el array
    • Devuelve el número total de registros que podría devolver la sentencia SQL completa.
  • Parámetros de entrada
    • El número de página de datos que deseo recuperar
    • El número de registros por página
    • Posibles datos para seleccionar en la clausula Where. Válido para la clave primaria del fichero o para otros campos.
    • Definir que ordenación deseo para la clausula Order
Con esta interfaz realizo el componente que podrá se llamado desde donde se desee. Por ejemplo de un programa de pantalla que presente una lista en un subfichero. Con los parámetros sería capaz de obtener un registro para la clave que desee, una lista de registros con la selección que haya establecido, solicitar una determinada página de datos, etc.

En otros artículos os dejaré el este código completo de este componente que además es reutilizable y similar para cualquier fichero.

No hay comentarios:

Publicar un comentario