23 septiembre, 2013
SQLRPGLE. ILERPG con SQL embebido.
Hoy voy a comentar como realizar un programa en ILERPG con sentencias SQL dentro de él. Es una técnica que cuando descubrí hace años me resultó muy práctica y que suelo usar habitualmente, sobre todo para hacer informes y consultas.
La idea es muy simple, y tras la explicación os pondré un ejemplo típico de un programa ILERPG que hace una consulta a la Base de Datos utilizando únicamente SQL.
Para empezar, lo primero que tenemos que hacer es decirle al compilador que mi programa es un programa ILERPG que lleva SQL en su interior, y esto lo hacemos indicándole simplemente que un archivo fuente del tipo SQLRPGLE. La única diferencia con un ILERPG normal son las sentencias SQL. De hecho, si lo compiláis sin ningún SQL en su interior simplemente os avisará de que no lleva nada, pero se compilará correctamente.
Una vez abierto el fuente SQLRPGLE simplemente, en las especificaciones de cálculo, en la posición que deseemos, debemos incluir las sentencias SQL entre 2 directrices del precompilador como son
C/EXEC SQL C+Aquí las sentencias SQL C/END-EXEC
Las sentencias SQL que incluyamos entre las 2 etiquetas deben ir precedidas del signo + y dentro de las mismas podemos referenciar a las variables del programa precediéndolas de dos puntos (:)
Dentro de las etiquetas podemos incluir cualquier tipo de sentencia SQL. Sentencias completas de ejecución como un UPDATE simple
C/EXEC SQL C+ UPDATE VCREPE C+ SET VCXEST = 'A' C+ WHERE VCXEST = ' ' C+ AND VCXFEF < :FECHA C+ AND VCXCAN >= 0 C/END-EXEC
O definición y ejecución de cursores, que es lo más interesante, y que me permite definir sentencias SELECT para acceder a la Base de Datos y realizar fácilmente consultas complejas.
Los pasos a seguir para realizar las consultas con cursores empiezan por la definición del mismo con su respectiva sentencia SELECT, su apertura, su bucle FETCH de lectura y, al final, su cierre.
Y como lo más práctico es que veáis un ejemplo, este código define un cursor y lo recorre. Aclarar que no es necesario definir los ficheros en las especificaciones F, tan sólo las variables que necesitemos para almacenar el resultado de la consulta.
C/EXEC SQL * Declaración del Cursor con la consulta C+ declare cur1 cursor for C+ select cfdart,sum(cfdcan),sum(cfdcan*cfdeur) C+ from cafdet, cafcab C+ where cfdnum=cfcnum C+ and cfdart between :dsarti and :arti2 C+ and cfcfec between :fec1 and :fec2 C+ and cfccli between :cli1 and :cli2 C+ group by cfdart C+ order by cfdart C/END-EXEC C/EXEC SQL * Apertura del Cursor C+ open cur1 C/END-EXEC * Bucle de Lectura C DO *HIVAL * C/EXEC SQL * Leemos el cursor y dejamos el resultado en las variable de RPG C+ fetch cur1 into :codart,:dscant,:dsimp C/END-EXEC * Controlamos el resultado por error o fin del cursor C SQLCOD IFLT 0 C SQLCOD OREQ 100 C LEAVE C ENDIF * * Proceso de los datos recuperados * C ENDDO C/EXEC SQL * cierro el cursor C+ close cur1 C/END-EXEC
Como veis, para controlar el resultado de cualquier sentencia que ejecutemos está el campo SQLCOD, que devuelve el código de error o situación en que finaliza una sentencia. En este caso, si es menor de 0 se ha producido un error o si es 100 es que hemos alcanzado el fin del cursor, con lo cual nos salimos del bucle.
Este es el código de un programa estándar de lectura de la base de datos. La mayoría de los que yo hago son prácticamente con esta estructura. Lo que suele complicarse es la sentencia SELECT para recuperar los datos hasta donde queráis o necesitéis.
Podeis declarar tantos cursores como necesitéis y recorrerlos en la secuencia que os convenga. A partir de ahí, cada uno puede complicarlo hasta todo lo que permite un lenguaje como SQL.
Necesito leer un archivo con sentencia select del sql ejcutar sobre ese registro leído algunos cambio y luego acutalizar con un comando sql
Update, Como se hace????
Buenas…. para lo que tú necesitas creo que está la sentencia WHERE CURRENT OF del UPDATE.
Si tienes una sentencia SQL que abre y va leyendo un cursor, para actualizar la fila leída usa la siguiente sentencia con los datos de tu tabla y el nombre del cursor que hayas abierto.
EXEC SQL
UPDATE nombre-tabla
SET column-1 = valor [, column-2 = valor] …
WHERE CURRENT OF nombre-cursor
END-EXEC.
Espero que te sea útil.
Hola Sergio
Para este tema existe la opción FOR UPDATE OF, aunque personalmente no la he usado nunca.
Mira si este enlace te sirve para lo que necesites
https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/sqlp/rbafyupdatingasretrieved.htm
Saludos
Mi caso es que después de realizar este proceso:
C/EXEC SQL
C+ UPDATE ARBIT2005/ARBIGR SET DIACER = 0, MESCER = 0, AÑOCER = 0,
C+ COEXE = :COECD2 WHERE DNIARB=:DNICD AND AGEARB=:AGECD AND
C+ DIACER=:DIACD AND MESCER=:MESCD AND AÑOCER=:AÑOCD AND DIAPAG=0
C+ AND COEXE=:COECD1
C/END-EXEC
Se queda bloqueado el registro afectado por el mismo.
Hola Alfonso, pues realmente no sé contestarte a este problema. Nunca se me ha dado.
Lo lamento
hola esos programas como se compilan con 14 o 15, gracias?
Hola, pues este programa se compila como otro cualquiera, con la opción 14, que al ser un tipo SQLRPLE usará el mandato CRTSQLRPGI
Hola una pregunta, puedo crear una tabla temporal para poder leer por medio de comando rpgle como read o como readp donde yo pueda recorrer los datos de la tabla temporal? o hay alguna forma por sql que yo pueda recorrer esa vista y valorar cada uno de los registros?
Buenos días
Para lo que creo que pretendes, es SQL tendrías que crearte un cursor con la selección de registros que desea, con la instrucción CREATE CURSOR.
Una vez creado y abierto usas la instrucción FETCH para recorrer los registros…. tiene muchas opciones para posicionarte en el primero, ultimo… o moverte hacia adelante o hacia atrás.
Si ves que te sirve o tienes alguna duda me lo dices…