viernes, 3 de diciembre de 2010

LOAD y UNLOAD: carga y descarga.



LOAD

La utilidad "LOAD" se utiliza para realizar "cargas" de datos a una tabla DB2.
La carga se realizará desde un fichero que puede venir con el formato de la tabla o no.

La estructura general de un paso de LOAD sería algo así:

//*================================================
//* CARGA DE LA TABLA TBPRU00
//* Donde los ficheros SORTWKXX son temporales para
//* ordenar la entrada
//* el SYSREC es el fichero con los datos para la carga
//* y el SORTOUT es temporal para ordenar la salida
//*======================================================
//LOADTBL EXEC DSNUPROC,SYSTEM=DSNP,UID=LOADIND
//DSNUPROC.SORTWK01 DD DSN=&&SORTWK01,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SORTWK02 DD DSN=&&SORTWK02,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SORTWK03 DD DSN=&&SORTWK03,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SORTWK04 DD DSN=&&SORTWK04,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SYSUT1 DD DSN=&&SYSUT1,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(5000,2000),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SYSREC DD DSN=XXXX.LOAD.TABLA,DISP=SHR
//DSNUPROC.SORTOUT DD DSN=&&SORT1,UNIT=SYSDA,
//    SPACE=(4000,(5000,2000),,,ROUND)
//SYSIN DD *


1. Vamos a ver en primer lugar el caso más sencillo, con un fichero de carga que tenga el mismo formato que la tabla:
//SYSIN DD *
LOAD


A continuación tendríamos varias opciones:
//*Si vamos a añadir registros
RESUME YES
INTO TABLE TBPRU00
LOG NO NOCOPYPEND
/*


//*Si vamos a reemplazar registros (se borrarán todos los que haya)
RESUME NO REPLACE
INTO TABLE TBPRU00
LOG NO NOCOPYPEND
/*


Utilizamos la opción RESUME para indicar si vamos a cargar datos en una tabla vacía o no:
RESUME YES: La tabla no está vacía, añadimos los registros de nuestro fichero.
RESUME NO: La tabla está vacía. Por si no lo estuviese, indicamos con REPLACE que reemplace los registros existentes por los de nuestro fichero.
La opción NOCOPYPEND se utiliza para quitar el estado COPY de la tabla y que quede accesible después de la LOAD.

2. Para el caso en que el fichero no tenga el mismo formato que la tabla tendríamos un paso de JCL similar, pero después de indicar el nombre de la tabla, indicaríamos para cada campo de la tabla, las posiciones que tiene el mismo campo en el fichero, y le daríamos el formato adecuado.

Vamos a suponer que nuestra tabla tiene el siguiente formato:
CAMPO1 S9(9) COMP-3.
CAMPO2 X(30).
CAMPO3 X(60).
CAMPO4 DATE
CAMPO5 S9(9) COMP-3.


Y que nuestro fichero tiene este otro:

Descripción campo        Posición
CAMPO1 PIC S9(9) COMP-3. 1
CAMPO2 PIC X(2).         6
CAMPO3 PIC X(1).         8
CAMPO4 PIC X(10).        9
CAMPO5 PIC 9(8).         19


En nuestra LOAD quedaría:
//SYSIN DD *
LOAD
RESUME NO REPLACE
INTO TABLE TBPRU00
(CAMPO1 POSITION(1:5) DECIMAL
,CAMPO2 POSITION(6:7) CHAR (2)
,CAMPO3 POSITION(8) CHAR (1)
,CAMPO4 POSITION(9:18) DATE EXTERNAL(10)
,CAMPO5 POSITION(19:26) DECIMAL EXTERNAL
)
LOG NO NOCOPYPEND


Un JCL completo podría ser:

//*===============================================
//* CARGA DE LA TABLA TBPRU00 *
//*===============================================
//LOADTBL EXEC DSNUPROC,SYSTEM=DSN1,UID=LOADIND
//DSNUPROC.SORTWK01 DD DSN=&&SORTWK01,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SORTWK02 DD DSN=&&SORTWK02,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SORTWK03 DD DSN=&&SORTWK03,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SORTWK04 DD DSN=&&SORTWK04,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(1000,700),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SYSUT1 DD DSN=&&SYSUT1,
//    DISP=(NEW,DELETE,DELETE),
//    SPACE=(4000,(5000,2000),,,ROUND),
//    UNIT=SYSDA
//DSNUPROC.SYSREC DD DSN=XXXX.LOAD.TABLA,DISP=SHR
//DSNUPROC.SORTOUT DD DSN=&&SORT1,UNIT=SYSDA,
//    SPACE=(4000,(5000,2000),,,ROUND)
//SYSIN DD *
LOAD
RESUME YES
INTO TABLE TBPRU00
LOG NO NOCOPYPEND
/*


Otros pasos útiles/opcionales cuando hacemos una LOAD:

Quitar estado COPY-pending
//*===================================================*
//* ANULAR COPY Y RECOVERY PENDIENTES *
//*==================================================*
//REPMES EXEC DSNUPROC,UID=TSPRU00
//SYSIN DD *
REPAIR SET TABLESPACE DBPRU.TSPRU00 NORCVRPEND
REPAIR SET TABLESPACE DBPRU.TSPRU00 NOCOPYPEND
/*


O también
//****************************************************
//* ABRE PARA R/W
//****************************************************
//ARRANGEN EXEC PGM=IKJEFT01,DYNAMNBR=20
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=4,DEST=JESTC3
//SYSTSIN DD *
DSN SYSTEM(DSN1)
-START DB(DBPRU) SPACE(TSPRU00) ACCESS(FORCE) <--tablespace

-START DB(DBPRU) SPACE(INPRU001) ACCESS(FORCE) <--índice /*

Poner tablespace/índices a UT (sólo permite acceder a la tabla a las utilitys)
//************************************************
//* STO: STOP STA: START
//******************************************************
//DSNTIAD1 EXEC PGM=IKJEFT01,DYNAMNBR=20
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM (DSN1)
-STO DATABASE(EXAMP001) SPACENAM(EXAMPTLF)
-STA DATABASE(EXAMP001) SPACENAM(EXAMPTLF) ACCESS(UT)
-STO DATABASE(EXAMP001) SPACENAM(IXAMPTLF)
-STA DATABASE(EXAMP001) SPACENAM(IXAMPTLF) ACCESS(UT)
END
/*


Poner tablespaces/índices a RW
//*************************************************
//* REALIZA UN START DE LECTURA/ESCRITURA SOBRE LA TABLA
//*******************************************************
//ARRANGEN EXEC PGM=IKJEFT01,DYNAMNBR=20
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=4,DEST=JESTC3
//SYSTSIN DD *
DSN SYSTEM (DSN1)
-STA DATABASE(EXAMP001) SPACENAM(EXAMPTLF) ACCESS(RW)
-STA DATABASE(EXAMP001) SPACENAM(IXAMPTLF) ACCESS(RW)
END
/*


Es recomendable hacer siempre una descarga previa, por lo que pueda pasar :P

UNLOAD

La utilidad "UNLOAD" sirve para realizar "descargas" de información de tablas.

La estructura general de un paso de UNLOAD sería algo así:

//*=================================================*
//* DESCARGA DE LA TABLA TBPRU00 *
//* Donde SYSPRINT contendrá mensajes de error
//* SYSPUNCH las sentencias de LOAD para una posterior
//* recarga de datos
//* y SYSRECnn es el fichero donde guardaremos la información
//*=======================================================*
//UNLOAD EXEC PGM=IKJEFT01,DYNAMNBR=20
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM(DSN1)
RUN PROGRAM(DSNTIAUL) PLAN(DSNTIAUL) -
LIB('LIBRERIA.DE.TU.INSTALACION')
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSPUNCH DD SYSOUT=*
//SYSREC00 DD DSN=XXXX.UNLOAD.TBPRU00,
//    DISP=(NEW,CATLG,DELETE),UNIT=SYSDA,
//    SPACE=(CYL,(100,50),RLSE)
//SYSIN DD *


En la SYSIN escribiremos la query para seleccionar los datos que queremos descargar. Por ejemplo:
SELECT *
FROM DSN1.TBPRU00 <-- El prefijo cambia según la instalación

WHERE CAMPO1 = 112 ORDER BY CAMPO2 ;

Esta SELECT se puede complicar tanto como queramos (SUBSELECTs, JOINs, etc).

Por supuesto, lo mejor en estos casos es buscar un JCL de carga o descarga que ya exista en tu entorno de explotación, y adaptarlo a tus necesidades ^^

14 comentarios:

Loboc dijo...

Buenas...añado una consulta que en caso de no conocer los tablespace ni los índices de una tabla nuestra puede ser útil:

SELECT SUBSTR(NAME, 1, 15) AS NAME ,
SUBSTR(DBNAME, 1, 15) AS DB,
SUBSTR(TSNAME, 1, 15) AS SPACE
FROM SYSIBM.SYSTABLES
WHERE NAME = 'XXXXXXXXXXXXXXX'
UNION
SELECT SUBSTR(NAME, 1, 15) AS NAME ,
SUBSTR(DBNAME, 1, 15) AS DB,
SUBSTR(INDEXSPACE, 1, 15) AS SPACE
FROM SYSIBM.SYSINDEXES
WHERE TBNAME = 'XXXXXXXXXXXXXXX';

Cambiar 'XXXXXXXXXXXXXXX' por nuestra tabla.

Podéis profundizar sobre esta consulta en el artículo http://www.google.es/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=4&ved=0CEYQFjAD&url=http%3A%2F%2Fwww.consultoriocobol.com%2F2010%2F12%2Fsystables-syscolums-y-sysindexes.html&ei=sOeOT--YNYGYhQewtuSHCw&usg=AFQjCNHAgTpgkWSwmESBQBKEOjs2egYBSQ

Anónimo dijo...

Hola
Como puedo hacer una descarga, pero en vez de darle los parametros directamente a la consulta, poder establecerlos desde otro archivo.

por ejemplo algo parecido a lo que hace la carga, que desde el archivo consigue los registros a cargar a la tabla, pero en lugar de que sean cargados estos puedan ser parametros de consulta y despues con los datos que salgan de la consulta generar un archivo como en la descarga.

agradeceria mucho si alguen me pudiera orientar. :D

Anónimo dijo...

Hola quiciera saber si hay una manera de insertar registros de un fichero a una tabla DB2 sin utilizar un programa batch, como lo hace el LOAD DATA REPLACE o el LOAD DATA RESUME, pero ellos no hacen actulizaciones

Loboc dijo...

Hola Anónimo, no nos queda muy clara tu pregunta. Los ejemplos expuestos en este artículo son JOBs no programas. Te agradecemos que nos aclares tus dudas para poder ayudarte. Un saludo y gracias por leernos.

LGS dijo...

Creo que Anónimo se refiere a lo siguiente: tenemos un fichero que contiene una serie de registros y en lugar de usar un programa que haga una serie de INSERT's intentarlo por jcl.

Si he entendido bien, creo que lo que habría que hacer sería lo siguiente:

1) Hacer UNLOAD de la tabla para tener en un fichero todos los registros existentes en la tabla -> fichero F1
2) El fichero F1 y el fichero que tú tienes, F2, los vamos a fusionar en un tercer fichero, F3, mediante paso de SORT.
3) El fichero F3 lo vamos a utilizar para cargar la tabla reemplazando registros.

Jesus dijo...

Buenas,
Tengo un problema con una descarga. Al terminar la entrada comentáis "Esta SELECT se puede complicar tanto como queramos (SUBSELECTs, JOINs, etc)", pues bien, yo quiero hacer un JOIN de dos tablas y no me funciona. Al ejecutar el JCL me da un error en la "," (coma) que separa las tablas. Es como si no supiera a cual de las dos tablas corresponde la descarga.
¿Me podéis ayudar?

Tallian dijo...

Hola Jesus.
En este artículo tienes un ejemplo de join en un Unload:
http://www.consultoriocobol.com/2010/12/sql-en-jcl.html

Si nos pasas la query completa que estás haciendo le echamos un ojo.

Gracias!

Africa Aragón dijo...

Os he mandado un mensaje con un error. Es con un hércules.
Gracias chicos

Africa Aragón dijo...

Lo consigo con la utilidad pero no con el JCL.
Alguna tontería será.
La vejez...
Un beso.

Africa Aragón dijo...

Todo arreglado!!!
Gracias de todas formas.

Tallian dijo...

Sorry África, lo acabo de leer!!

Anónimo dijo...

primero se le saluda.
Tengo una consulta de principiante, estoy mirando tu explicacion y ayuda con respecto al LOAD, la pregunta es "por definición, tienen que definirse tantas areas de trabajo y porque", le agradeceria comentarlo, se agradece.
saluda cordialmente.
Jaime

Soy yoS dijo...

hola, una consulta, voy a generar un fichero con las sentencias unload de una serie de tablas en un programa, ¿como puedo ejecutarlas desde el jcl cogiendo este fichero?.
Saludos.

Unknown dijo...

Gracias por su ayuda, me aclaró mis dudas sobre LOAD RESUME y REPLACE