Bienvenidos a Iseries Venezuela

Las mejores prácticas, recursos, tips, enlaces, videos y artículos para informáticos relacionados con el Iseries y el As/400 lenguajes de programación RPG, ILE RPG y SQL.

The best practices, resources, tips, links, videoes and articles for computer related to the Iseries and the As/400 languages of programming RPG, ILE RPG and SQL.
Showing posts with label SQL. Show all posts
Showing posts with label SQL. Show all posts

Thursday, August 4, 2016

Cursores en SQL Para Programadores en RPG (3/3)


                                                     
Cursores en SQL  (3 de 3)
Conceptos sencillos pero poderosos
a tu alcance.                                                      

                                                                                                                                                                                                                                                               




                                                                                                                                                                                                                                                                  

Si te pareció interesante, reenvíalo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo. 
Autor: Ing. Liliana Suárez

Tuesday, July 26, 2016

Tipo de Cursores (2/3) ¿Para que me sirven?



En esta entrega puedes ver los tipos de cursores en SQL y cómo se clasifican. Así podrás determinar cual  es el mas óptimo según el desarrollo que estés realizando SQLRPG.

                                                    


                                                                                                                                                                                                                                                               




                                                                                                                                                                                                                                                                  

Si te pareció interesante, reenvíalo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo. 
Autor: Ing. Liliana Suárez

Friday, June 28, 2013

Ejemplo SQLRPG y %LIKE para Búsqueda de Textos o Cadenas de Caracteres















Algunas veces puede resultar confuso manejar el %Like dentro del SQL embebido.
En esta oportunidad les entrego un código descargable como un ejemplo de como
manejar el like en un SQLRPGLE



Si colocas en BUSCAR un texto, desplegara en pantalla todos los municipios que tengan
ese string de caracteres en este caso: ANTONIO      

En este enlace puedes descargar el código fuente del programa y los archivos correspondientes
residentes en el archivo SQLLIKE.ZIP.

http://sdrv.ms/17WfsjI

Pd: Gracias a Frank Ronald por la sugerencia de publicar este tema.

Si te pareció interesante, reenvíalo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor: Ing. Liliana Suárez
 

Friday, February 8, 2013

SQL Embebido - Sentencia USING y algo mas...


 
 
          SQL EMBEBIDO

          Sentencia USING


Cuando hacemos SQL dinámicos  requerimos construir dinámicamente la instrucción SELECT para extraer los registros que necesitamos de la base de datos. Muchas veces  las condiciones de selección son cambiantes  porque los valores de búsqueda son distintos dependiendo del proceso. En el programa, utilizamos variables  que contienen el valor de búsqueda de uno o varios campos dentro de las tablas de datos.  Las variables en el algoritmo de programación van teniendo valores  cambiantes y no es posible  colocar en Hard Code (código duro)  la sentencia SELECT del SQL. La sentencia “USING” permite solucionar este inconveniente.

 

Supongamos que tenemos que generar un reporte de inventario para varias filiales de una corporación. Tenemos en la base de datos una tabla de empresas filiales:

01= filia1  02= filial2  03 = filial3

En RPG FREE

1.-Declaramos las variables de trabajo para construir la sentencia dinámica

D Varsql1         s           1000a    Inz(*Blanks)

D V_Sql1          s           1000a

2.-Construimos la sentencia dinámica.

 (Como no sabemos la compañía que hay listar  colocamos = ?

exec sql set :V_SQL1 =       

  'select *    '||           

  'from INVENTARIO   '||         

  'Where CIA = ? '    ||  

  'order by CIA';        

3.-Ejecutamos el PREPARE

exec sql Prepare varsql1 From :v_sql1;

4.-Declaramos el Cursor.

exec  sql Declare c1 dynamic Scroll Cursor for varsql1

5.-Ejecutamos el OPEN del Cursor

 exec sql open c1 using :Var_CIA;

En este punto, se entiende que serán procesados aquellos registros de la base de datos

Cuyo valor en el campo compañía sea igual al valor del contenido de la variable: Var_CIA

 

6.- Ejecutamos el Fetch que sea requerido

exec sql fetch next from c1 into :Filler

 
                                          
 

Un caso menos obvio en su programación es el %LIKE% para armar la sentencia SQL. (Like = que contenga algo parecido a este texto)

Para utilizar el %LIKE%  es necesario primero construir el contenido de la variable que será aplicada en el USING en forma adecuada. Es decir en este caso la variable:  Var_Cía no debería contiene un valor numérico o alfabético sino que es el resultado de la concatenación de varios elementos que hacen posible para el SQL interpretar lo que se está pidiendo procesar.

Por ejemplo, supongamos que queremos buscar una dirección que tenga la palabra MADRID. En este caso requerimos el uso del LIKE de la siguiente manera:

Utilizamos una variable que llamaremos CIUDAD bien sea que el usuario la introduzca por pantalla o que la manipulemos en el programa.

CIUDAD = MADRID

Vamos a denominar a la variable colocada en la sentencia USING como: QRY_CIUDAD

Hacemos lo siguiente:

QRY_CIUDAD = ‘%’ + %trim(CIUDAD) + ‘%’

La sentencia SQl la podemos construir normalmente:

exec sql set :V_SQL1 =

                    'select ESTADO, CIUDAD, Descri '||

                    'from libsuarez/ciudades '||

                    'Where ciudad like  ? '    ||

                    'order by ciudad';

Cuando abrimos el cursor podemos colocar

exec sql open c1 using :QRY_CIUDAD;

 

 

Si te pareció interesante, reenvíalo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor: Ing. Liliana Suárez

Friday, December 7, 2012

Equivalencia SQL Vs. RPG






 
 
Orientado a aquellos programadores en RPG que deben lidiar con códigos en Sql con los que no están muy familiarizados.

En esta oportunidad hacemos una equivalencia entre el comando Fetch del Sql y las sentencias de lectura y posicionamiento del RPG, RPGLE.

Con los siguientes comandos es posible construir un programa que permita manipular el subfile en grupo de n filas y realizar el avance y retroceso de página adecuado, así como el posicionamiento y las búsquedas que sean requeridas.

Repasamos la función DECLARE en la cual debemos declarar un cursor dinámico para poder acceder a un posicionamiento “random” en el archivo.

Luego de declarar el cursor Scroll dinámico, con las condiciones de Select que hagan falta, realizamos el open del cursor y luego con un fetch before nos posicionamos al principio de la tabla. Esto seria el Setll del rpg, luego con un fetch next realizamos lo que sería un read en rpg. El “fin de archivo” lo hace el sqlcode <> 0.

Equivalencias SQL Vs RPG

Fetch prior = READP

Fetch After = Setgt  se coloca al final de la tabla resultado de la selección

Fetch Before = Setll se coloca al principio de la tabla resultado de la selección

Fetch relative ( +n, -n)  se posiciona n filas adelante o – n filas atrás de la ultima fila leída

Fetch first =  trae el primer registro de la tabla resultado de la selección

Fetch last = trae el ultimo registro de la tabla resultado de la selección

Fetch current = re-lee el registro que se acaba de leer

Fetch Next = read. Lee el siguiente

__________________________________________

Un ejemplo sencillo de lectura de N en N registros hacia adelante es:

exec sql declare c1    dynamic scroll cursor for     //esto se “declara una sola vez”  en

                                                                                            el programa, a menos que se

                                                                                           quiera modificar 
                                                                                           la sentencia select//

select *                       

from libreria/archivo                          

order by clave;                          

exec sql open c1;            

exec sql fetch before from c1;  //setll

exec sql fetch next from c1 into Dsdata  //read

Cuenta = 1

Dow sqlcode = 0 and cuenta < N;  

//instrucciones que hagan falta

Cuenta = cuenta +1;

exec sql fetch next from c1 Dsdata;   //read

enddo;         

Un ejemplo sencillo  de lectura de N en N registros hacia atrás es:

exec sql                                                      

exec sql declare c1    dynamic scroll cursor for     //esto se declara una sola vez en el pgm

select *                       

from libreria/archivo                          

order by clave;                          

Rrn    = N+1;                               

exec sql fetch prior from c1 into :Dsdata; //readp

Dow sqlcode  = 0 and cuenta  > 1 ;      

cuenta  -= 1;    

//instrucciones que hagan falta                        

exec sql fetch prior from c1 into :Dsdata;

Enddo;            

Estos comandos son particularmente útiles cuando queremos cargar un subfile de n en n registros haciendo retroceso y avance de página utilizando sentencias Sql que nos liberan de la necesidad de crear lógicos adicionales para posicionamiento u ordenamiento.

     

Si te pareció interesante, reenvíalo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor: Ing. Liliana Suárez
                 

Monday, February 20, 2012

Stored Procedure. ¿Que es eso?











El Db2 Sql provee para el iseries o para el AS400 una herramienta para invocar programas o procedimientos (procedures) en instrucciones SQL.

Cuando el procedimiento almacenado o Stored Procedure se trata de un programa en un lenguaje de código distinto al SQL tal como RPG, Java, C u otros, se define un External Stored Procedure, para indicarle al Db2 SQL que debe invocarse un ejecutable escrito en otro lenguaje de programación. Al momento de crear un store procedure se especifica el nombre, los parámetros que utilizará y –en el caso de External Stored Procedures- se especifica además, el lenguaje de programación en el que está escrito.
El Stored Procedure se puede crear con comandos del SQL Embebido o con El SQL interactivo. El siguiente, es un ejemplo de External Store Procedure:

EXEC SQL CREATE PROCEDURE P1
                     (INOUT PARM1 CHAR(10))
                    EXTERNAL NAME MYLIB.PROC1
                    LANGUAGE C
                    GENERAL WITH NULLS;
 
Se especifica el nombre del programa, la librería donde reside, los parámetros de llamada y el lenguaje en el que está escrito. Se indica además que el parámetro de llamada PARM1 puede contener valores nulos y es de I/O. (recibe valores y también los modifica)


Podemos invocar un Stored Procedure de la siguiente manera:

  DCL HV1 CHAR(10);
     DCL IND1 FIXED BIN(15);
        :
     EXEC SQL CREATE P1 PROCEDURE
               (INOUT PARM1 CHAR(10))
               EXTERNAL NAME MYLIB.PROC1
               LANGUAGE C
               GENERAL WITH NULLS;
        :
     EXEC SQL CALL P1 (:HV1 :IND1);
 
Podemos invocar un Stored Procedure suponiendo que ya está creado previamente:
 
DCL HV2 CHAR(10);
        :
     EXEC SQL CALL P2 (:HV2);
 
Los ejemplos anteriores son “estáticos” es decir, se crea el Stored Procedure o se presume que ya fue creado y luego se invoca con un CALL.
 
Puede hacerse un Stored Procedure Dinámico en el que se invoca, creándolo en el mismo momento en que se realiza la llamada.
 
 
char hv3[10],string[100];
           :
       strcpy(string,"CALL MYLIB.P3 ('P3 TEST')");
       EXEC SQL EXECUTE IMMEDIATE :string;
           :
 
Escrito en lenguaje C, la funcion Strcpy se interpreta de la siguiente manera: 

strcpy( variable destino, cadena fuente )
 
para los que estamos mas familiarizados con RPG, diríamos que, el execute Inmediate seria equivalente a una llamada a la utilidad QCMDEXEC pasandole en un string, el comando a ejecutar.
 
 
Un Stored Procedure en código Db2 Sql sería el siguiente:
 
EXEC SQL CREATE PROCEDURE UPDATE_SALARY_1
 |            (IN EMPLOYEE_NUMBER CHAR(10),
 |             IN RATE DECIMAL(6,2))
 |             LANGUAGE SQL MODIFIES SQL DATA
 |             UPDATE CORPDATA.EMPLOYEE
 |               SET SALARY = SALARY * RATE
 |               WHERE EMPNO = EMPLOYEE_NUMBER;
 
 
 

También puede crearse un Stored Procedure que solo lea Data:

EXEC SQL CREATE PROCEDURE UPDATE_SALARY_1
 |            (IN EMPLOYEE_NUMBER CHAR(10),
 |             IN RATE DECIMAL(6,2))
 |             LANGUAGE SQL READS SQL DATA
 |             Select name, area from Library/File_employee
 |               WHERE EMPNO = EMPLOYEE_NUMBER;




El material sobre el Stored Procedure es extenso y tiene su sintaxis en definición y tipo de parámetros, principio (BEGIN)  y fin de procedure (END) y otros. El material en Ingles lo pueden conseguir en con mayor detalle en este enlace.


Si te pareció interesante, reenvíalo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.


Autor: Ing. Liliana Suárez

Thursday, December 16, 2010

SQL y el JOIN



                        






En el manejo del SQL el empleo del JOIN es muy importante para realizar búsquedas en la base de datos y sobretodo para comprobar la integridad de la data.
Existen tres tipos de JOIN: INNER JOIN, LEFT JOIN, RIGHT JOIN.
Vamos a ver con un ejemplo como funcionan estos JOIN.

Supongamos que tenemos dos bases de datos:

La base de datos EMPLEADOS que contiene la siguiente información.
Clave = Id, Nacionalidad

Id. 5886825
Nombre= Pedro Perez
Nacionalidad = USA

Id. 66677889
Nombre = Juan Rodríguez
Nacionalidad = MEX

La base de Datos SUELDOS que contiene la siguiente información:
Clave = ID, NACIONALIDAD, DEPARTAMENTO

Id. 5886825
Nacionalidad = USA
Sueldo = 5000,00
Departamento = Contabilidad.

Id. 444333221
Nacionalidad = BOL
Sueldo = 8000,00
Departamento = Finanzas


En este momento Juan Rodríguez no ha sido asignado a ningún departamento.

La denominación Archivo1 se lo asignamos a la Base de Datos  EMPLEADOS
La denominación Archivo2 se lo asignamos a la base de Datos SUELDOS


Vamos a ver cual es el resultado de la consulta cuando trabajamos con INNER JOIN:


SELECT Archivo1.ID, Archivo2.ID, Archivo1.NOMBRE, Archivo2.SUELDO INNER JOIN SUELDOS Archivo2 ON  Archivo1.ID = Archivo2.ID and Archivo1.NACIONALIDAD = Archivo2.NACIONALIDAD.

El resultado de la búsqueda es:

5.886.825, 5.886.825, Pedro Perez. 5000

Esto corresponde en la imagen al área de color amarillo de la figura, donde están los empleados que se encuentran en ambas bases de datos.


Vamos a ver cual es el resultado de la consulta cuando trabajamos con LEFT JOIN:

SELECT Archivo1.ID, Archivo2.ID, Archivo1.NOMBRE, Archivo2.SUELDO LEFT JOIN SUELDOS Archivo2 ON  Archivo1.ID = Archivo2.ID and Archivo1.NACIONALIDAD = Archivo2.NACIONALIDAD.

66.677.889, NULL, Juan Rodríguez. NULL

Esto corresponde en la imagen al área de color azul de la figura, donde están los empleados que se encuentran SOLO en la base de datos: EMPLEADOS.


Vamos a ver cual es el resultado de la consulta cuando trabajamos con RIGHT JOIN:

SELECT Archivo1.ID, Archivo2.ID, Archivo1.NOMBRE, Archivo2.SUELDO RIGHT JOIN SUELDOS Archivo2 ON  Archivo1.ID = Archivo2.ID and Archivo1.NACIONALIDAD = Archivo2.NACIONALIDAD.

NULL, 444333221, NULL, 8000

Esto corresponde en la imagen al área de color verde de la figura, donde están los empleados que se encuentran SOLO en la base de datos: SUELDOS. Este último resultado nos está señalando que no hay integridad en la Base de Datos y debemos revisar que está ocurriendo.



Autor: Ing. Liliana Suárez.


Si te pareció interesante el artículo reenvíalo a un amigo, haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.



Monday, February 15, 2010

Tips Generales para optimizar Query/SQL


Algunos tips que te ayudarán a que tus queries se ejecuten tan rápidos como sea posible


1- Crear  índices de acceso cuya clave posicionada más a la izquierda del query haga match con las condiciones de selección, ayuda al optimizador de búsqueda con la selección de valores.

2- Para realizar queries con join, crear indices que hacen “match” con las columnas del join ayuda al optimizador de búsqueda a determinar el promedio de filas que hacen “matching”

3- Especificar solo las columnas que necesitas para el query en la sentencia SELECT en lugar de especificar *. También podrías especificar FOR FETCH ONLY si las columnas no requieren ser actualizadas.

4- Utilizar el comando RGZPFM. Reorganize Physical File Membre para remover
Las filas eliminadas de las tablas. Utilizar el comando CHGPF REUSEDLT(*YES) para reusar las filas eliminadas.

5- Considera usar las siguientes opciones:
Especificar ALWCPYDTA(*OPTIMIZE) permite al optimizador del query crear copias temporales de data para obtener un mejor performance. The iSeries® Access ODBC driver y el  Query Management driver siempre usan esta modalidad. Si ALWCPYDTA(*YES) es especificado, el optimizador de búsqueda intentará implementar el query sin hacer copia de la data, pero creará una copia si así se requiere.  Si ALWCPYDTA(*NO) es especificado, copias de la data no serán permitidas. Si el optimizador del query no puede encontrar un modo de búsqueda que no requiera el uso de un almacenamiento temporal, entonces el query no puede ser ejecutado.
OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
   GRPFLD(JOB SALARY)
   KEYFLD(JOB SALARY)
   SRTSEQ(*LANGIDUNQ) LANGID(ENU)
   ALWCPYDTA(*OPTIMIZE)

6- Especificar DLYPRP(*YES) para retardar  la validación de la sentencia SQL hasta que una sentencia OPEN, EXECUTE, o DESCRIBE sea ejecutada. Esta opción mejora el tiempo de respuesta, eliminando validaciones redundantes.
C/Exec SQL
C+ Set Option Commit=*NONE, DatFmt=*ISO, DynUsrPrf=*Owner, DlyPrp=*YES
C/End-Exec

7- Para el SQL, usar CLOSQLCSR(*ENDJOB) o CLOSQLCSR(*ENDACTGRP) permite que las vías de acceso abiertas, permanezcan abiertas para futuras invocaciones. (CRTSQLXXX)

8- Usar  ALWBLK(*ALLREAD) permite al manejador bloquear el registro  de data para cursores de “solo lectura”.  SET OPTION ALWBLK = *ALLREAD 

Valores para ALWBLK:

*ALLREAD 

Las filas son bloquedas para “solo lectura” si el parámetro COMMIT es *NONE o *CHG. Todos los cursores en un programa que no son explícitamente utilizados para update serán abiertos para read-only aún cuando las sentencias EXECUTE o EXECUTE IMMEDIATE estén presentes en el programa.

Puede mejorar el performance de casi todos los cursores read-only en programas
Pero limita el query de las siguientes maneras:

El comando Rollback en el lenguaje anfitrión (ile RPG, RPG) ó la sentencia ROLLBACK HOLD SQL no reposiciona el cursor read-only.

La ejecución dinámica de una sentencia UPDATE o DELETE (por ejemplo usando EXECUTE IMMEDIATE) no pueden ser utilizada para actualizar una fila a menos que la sentencia DECLARE para la declaración del cursor incluya la cláusula FOR UPDATE.


*NONE 
Las filas no son bloqueadas para devolver la data a los cursores.
Garantiza que la data devuelta en la consulta está actualizada.
Puede reducir la cantidad de tiempo requerido para acceder la primera fila de la data.
Impide que el manejador de base de datos devuelva un bloque de data que no es utilizada por el programa cuando solamente las primeras filas del query son las requeridas.
Puede degradar el performance del query si la consulta devuelve un gran número de filas.


*READ 
Los registros son bloqueados para read-only cuando:

*NONE es especificado en el parámetro COMMIT, lo que indica que el commitment control no es utilizado

El cursor es declarado FOR READ ONLY o no hay una sentencia dinámica que pudiese ejecutar una sentencia UPDATE o DELETE posicionado por cursor.

Especificar *READ puede mejorar el performance total del query cuando una gran cantidad de registros cumplen con las condiciones de búsqueda.






Publicado por: Ing. Liliana Suárez.


Si te pareció interesante el artículo reenvíalo a un amigo, haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.

Thursday, November 5, 2009

Sql para eliminar registros duplicados
















Eliminar registros con clave duplicada de un archivo utilizando SQL.



DELETE FROM LIBRERIA1/ARCHIVO1 where RRN(F1) > (Select MIN(RRN(F2)) From LIBRERIA1/ARCHIVO1 F2 WHERE F2.CLAVE = F1.CLAVE)



Debe leerse el comando de derecha a izquierda como las escrituras árabes. En este caso comenzando con el Select.

Este comando trabaja con el Record Number (Número de registro físico) con el que trabaja el Iseries al grabar los registros en un archivo. La palabra clave es: RRN.

El comando selecciona el menor record Number entre registros del mismo archivo con claves coincidentes. F1 y F2 son artificios usados por Sql para identificar rapidamente un archivo de otro archivo. El resultado de un select es una tabla interna subconjunto del archivo original,  cuyos registros coinciden con F1 (que tambien es el archivo original)  pero seleccionando el  registro con menor Record Number. Seguidamente, el comando procede a eliminar (DELETE) del archivo original el registro duplicado con mayor Record Number.




Si te pareció interesante, reenvialo a un amigo haciendo click en el sobrecito que está al final del artículo. El conocimiento es valioso, compártelo.

Autor: Ing. Liliana Suárez