Objetivos:
• Leer archivos de texto con PL/SQL.
• Procedimiento GET_LINE del Paquete UTL_FILE.
• Ver ejemplos de uso práctico.
____________________________________________________________________________________
Procedimiento GET_LINE.
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.
|
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.*/
---
SET SERVEROUTPUT ON
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.