Objetivos:
- Leer archivos de texto con PL/SQL.
- Procedimiento GET_LINE del Paquete UTL_FILE.
- Ver ejemplos de uso práctico.
Procedimiento GET_LINE
Ver Manejando Archivos de Texto con PL/SQL (UTL_FILE): Para mas información y ejemplos del Paquete UTL_FILE.
El Procedimiento GET_LINE lee texto del archivo tipo UTL_FILE.FILE_TYPE previamente abierto y coloca el texto en el parámetro de salida búfer. El texto es leído hasta el terminador de línea(Sin incluir dicho terminador) o hasta el final del archivo o hasta el final del parámetro len. No es posible exceder max_linesize especificado en FOPEN.
Nota: Si la línea no cabe en el búfer, se genera la excepción VALUE_ERROR. Al llegar al final del archivo y no encontrar texto alguno, se genera la excepción NO_DATA_FOUND. Si se abre el archivo para operaciones en modo byte (RB, WB, AB) o modo escritura (W), se genera la excepción INVALID_OPERATION.
Sintaxis:
UTL_FILE.GET_LINE
(
file IN FILE_TYPE,
buffer OUT VARCHAR2,
len IN PLS_INTEGER DEFAULT NULL
);
Donde:
Parámetro |
Descripción |
file |
Identificador de archivo activo retornado por la llamada de FOPEN.
El archivo debe estar abierto en modo lectura (R); De lo contrario se genera la excepción INVALID_OPERATION. |
buffer |
Búfer de datos para recibir la línea leída del archivo |
len |
El número de bytes leídos del archivo. El valor predeterminado es NULL. Si es NULL, Oracle proporciona el valor de max_linesize. |
Ejemplos:
CREATE OR REPLACE DIRECTORY dir_read
AS 'F:\Directory_Read';
/*Primero creamos un directorio de Base de Datos con la ruta donde residirá el Archivo a ser leído. Nota: El directorio físico (La Carpeta) debe ser creado manualmente.*/
/*La anterior imagen muestra el directorio físico creado manualmente. También notar el Archivo: Source_File.txt a ser leído con el procedimiento GET_LINE.*/
/*La anterior imagen muestra el contenido del archivo: Source_File.txt. Click Aquí para Descargar.*/
DECLARE TYPE typ_rec IS RECORD ( line NUMBER, column VARCHAR2(14) ); TYPE typ_field IS TABLE OF typ_rec; v_field typ_field; v_last NUMBER := 0; v_file UTL_FILE.FILE_TYPE; v_line VARCHAR2(500); BEGIN v_file := UTL_FILE.FOPEN ( 'DIR_READ', --Nombre del Directorio en Mayúsculas 'Source_File.txt', 'R' ); LOOP BEGIN v_field := typ_field(); UTL_FILE.GET_LINE(v_file, v_line); FOR i IN 1..6 LOOP v_field.EXTEND; v_field(i).line := INSTR(v_line,'|',v_last+1,1); CASE WHEN i = 1 THEN v_field(i).column := 'LINE'; WHEN i = 2 THEN v_field(i).column := 'NAME'; WHEN i = 3 THEN v_field(i).column := 'NATIONALITY'; WHEN i = 4 THEN v_field(i).column := 'AGE'; WHEN i = 5 THEN v_field(i).column := 'MARITAL_STATUS'; ELSE v_field(i).column := 'CHILDREN_COUNT'; END CASE; v_last := v_field(i).line; END LOOP; v_last := 0; DBMS_OUTPUT.PUT_LINE(RPAD('=',LENGTH(v_line),'=')); DBMS_OUTPUT.PUT_LINE(v_line); DBMS_OUTPUT.PUT_LINE(RPAD('=',LENGTH(v_line),'=')); DBMS_OUTPUT.PUT_LINE(v_field(1).column||': '||SUBSTR(v_line,1,v_field(1).line-1)); FOR i IN 1..5 LOOP DBMS_OUTPUT.PUT_LINE(v_field(i+1).column||': '|| SUBSTR ( v_line,v_field(i).line+1,v_field(i+1).line-v_field(i).line-1 ) ); END LOOP; DBMS_OUTPUT.PUT_LINE('VEHICLE: '||SUBSTR(v_line,v_field(6).line+1,LENGTH(v_line))); EXCEPTION WHEN NO_DATA_FOUND THEN EXIT; END; END LOOP; UTL_FILE.FCLOSE(v_file); END;
/*Sin dar muchos detalles, en este ejemplo vemos como usamos el procedimiento GET_LINE para recorrer linea por linea el archivo en cuestión y asignar a la variable de salida el valor contenido. Notar que el mismo procedimiento lee una linea a la vez y avanza a la siguiente, una vez que no encuentra mas lineas se produce la EXCEPTION: NO_DATA_FOUND.*/
---OUTPUT:
CREATE TABLE hr.people_details
(
line NUMBER,
name VARCHAR2(50),
nationality VARCHAR2(50),
age NUMBER(2),
marital_status VARCHAR2(15),
children_count VARCHAR2(9),
vehicle VARCHAR2(50)
);
/*Creamos la tabla: people_details donde insertaremos los datos extraídos del Archivo: Source_File.txt.*/
DECLARE TYPE typ_rec IS RECORD ( line NUMBER, v_people hr.people_details%ROWTYPE ); TYPE typ_field IS TABLE OF typ_rec; v_field typ_field; v_last NUMBER := 0; v_file UTL_FILE.FILE_TYPE; v_line VARCHAR2(500); BEGIN v_file := UTL_FILE.FOPEN ( 'DIR_READ', --Nombre del Directorio en Mayúsculas 'Source_File.txt', 'R' ); LOOP BEGIN v_field := typ_field(); UTL_FILE.GET_LINE(v_file, v_line); FOR i IN 1..6 LOOP v_field.EXTEND; v_field(i).line := INSTR(v_line,'|',v_last+1,1); v_last := v_field(i).line; END LOOP; v_last := 0; v_field(1).v_people.line := SUBSTR(v_line,1,v_field(1).line-1); v_field(1).v_people.name := SUBSTR ( v_line,v_field(1).line+1,v_field(2).line-v_field(1).line-1 ); v_field(1).v_people.nationality := SUBSTR ( v_line,v_field(2).line+1,v_field(3).line-v_field(2).line-1 ); v_field(1).v_people.age := SUBSTR ( v_line,v_field(3).line+1,v_field(4).line-v_field(3).line-1 ); v_field(1).v_people.marital_status := SUBSTR ( v_line,v_field(4).line+1,v_field(5).line-v_field(4).line-1 ); v_field(1).v_people.children_count := SUBSTR ( v_line,v_field(5).line+1,v_field(6).line-v_field(5).line-1 ); v_field(1).v_people.vehicle := SUBSTR(v_line,v_field(6).line+1,LENGTH(v_line)-v_field(6).line); INSERT INTO hr.people_details VALUES v_field(1).v_people; EXCEPTION WHEN NO_DATA_FOUND THEN EXIT; END; END LOOP; UTL_FILE.FCLOSE(v_file); END;
/*Ahora modificamos el pasado ejemplo para que en lugar de mostrar los datos por pantalla, inserte dichos valores en la tabla: people_details.*/
---OUTPUT:
Nota: En los ejemplos antes presentados, aparte de implementar la funcionalidad del paquete UTL_FILE también uso otros objetos como TYPES y Estructuras de Control de la que no doy detalles, esto es debido a que dichos objetos han sido explicados en pasadas publicaciones del BLOG. Aun así, si sienten algún tipo de duda o confusión pueden exponerlas con libertad vía comentario o mensaje privado.