Oracle
 sql >> Database >  >> RDS >> Oracle

Lettura e importazione di file CSV in Oracle PL/SQL in modo efficiente

L'esempio è riportato di seguito per leggere e importare CSV file (delimitato da virgole) in PLSQL. C'è un pacchetto in Oracle Forms "D2k_Delimited_String" che usiamo per leggere e importare file delimitati da virgole (o qualsiasi delimitatore), ho scritto un post anche su Oracle Forms per leggere i file delimitati con questo pacchetto, il seguente è il link https:/ /www.foxinfotech.in/2013/02/reading-and-importing-comma-delimited.html. Lo stesso pacchetto che ho convertito in pacchetto di database per leggere il file CSV in PLSQL in modo efficiente, ho rinominato il pacchetto in "Plsql_Delimited_String". Di seguito è riportato un esempio per importare file CSV in PL SQL con l'aiuto di questa funzione del pacchetto Get_String, il seguente è l'utilizzo di questa funzione:

Plsql_Delimited_String.Getstring ([stringa contenente testo delimitato, l'intera riga],
[occorrenza],
[valore predefinito booleano non terminato false],
[delimetro]);

Nella procedura seguente l'utente passerà un nome file che dovrebbe trovarsi nella posizione della directory creata nell'oggetto directory Oracle, in questo esempio viene utilizzato l'oggetto directory 'YOUR_DIRECTORY', cambiarlo con l'oggetto directory e copiare il file delimitato in quella posizione, quindi passare il nome del file a questa procedura.

PROCEDURA CREA O SOSTITUZIONE Import_Emp_File (P_FILENAME IN VARCHAR2,
o_msg OUT VARCHAR2)
IS
Infile UTL_FILE.File_Type;
Linebuf VARCHAR2 (4000);
V_Getstring VARCHAR2 (100 );

-- Matrice di valori di campo
TYPE Fieldvalue IS TABLE OF VARCHAR2 (100)
INDEX BY BINARY_INTEGER;

Field_Position Valore campo;

Total_Rec_Count NUMBER :=0;
Total_Rec_Processed NUMBER :=0;
BEGIN
Infile :=UTL_FILE.Fopen ('YOUR_DIRECTORY', P_FILENAME, 'R');

LOOP
---
UTL_FILE.Get_Line (Infile, Linebuf);
-- aggiunta di pipe extra alla fine della riga per leggere tutti i campi

Linebuf :=Linebuf || '|';

-- Supponiamo che il file contenga sei stringhe delimitate con pipe (|)
FOR I IN 1 .. 6
LOOP
Field_Position (I) :=
Plsql_Delimited_String.Getstring (Linebuf ,
I,
FALSE,
'|');
END LOOP;

BEGIN
Conteggio_rec_totale :=Conteggio_rec_totale + 1;

-- una tabella di esempio
INSERT INTO EMP (EMPLOYEE_NUMBER,
FIRST_NAME,
LAST_NAME,
DATE_OF_JOIN,
EMP_TYPE,
DATE_OF_REGN)
VALUES (posizione_campo (1),
posizione_campo (2),
posizione_campo (3),
posizione_campo (4),
posizione_campo (5),
posizione_campo (6) );

Total_Rec_Processed :=Total_Rec_Processed + 1;
ECCEZIONE
QUANDO ALTRI
ALLORA
-- ignorando l'errore durante l'inserimento del database
NULL;
END;
FINE CICLO;

IF UTL_FILE.is_open (infile)
THEN
UTL_FILE.Fclose (Infile);
END IF;
ECCEZIONE
QUANDO NO_DATA_FOUND
ALLORA
IF UTL_FILE.is_open (infile)
THEN
UTL_FILE.Fclose (Infile);
END IF;

IF total_rec_processed> 0
THEN
COMMIT;
END IF;
QUANDO ALTRI
THEN
IF UTL_FILE.is_open (infile)
THEN
UTL_FILE.Fclose (Infile);
END IF;

o_msg :=SQLERRM;
END;
/Di seguito è riportato l'origine del pacchetto di PLSQL_DELIMITED_STRING utilizzato in questo esempio, installa questo pacchetto nel tuo schema. Il pacchetto contiene molte altre funzioni di utilità che possono essere utilizzate per leggere il file CSV utilizzando PLSQL:

CREA O SOSTITUISCI IL PACCHETTO plsql_Delimited_String IS

function Counter( Source_string in varchar2,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',') return number;
Procedura PutString( Source_string in out varchar2,
String_to_add in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',');
Procedura PutNumber( Source_string in out varchar2,
number_to_add in number,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimitatore in varchar2 default ',');
Procedura PutDate( Source_string in out varchar2,
Date_to_add in date,
Field_position in number,
UnTerminated in Bo olean default FALSE,
Delimiter in varchar2 default ',');
function GetString( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimitatore in varchar2 default ',') return varchar2;
function GetNumber( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimitatore in varchar2 default ', ') return number;
function GetDate( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimitatore in varchar2 default ',') return date;
funzione Locate( Source_string in varchar2,
Search_String in varchar2,
UnTerminated in Boole an default FALSE,
Delimiter in varchar2 default ',') return number;
function Locate( Source_string in varchar2,
Search_date in date,
UnTerminated in Boolean default FALSE,
/> Delimiter in varchar2 default ',') return number;
function Locate( Source_string in varchar2,
Search_number in number,
UnTerminated in Boolean default FALSE,
Delimitatore in varchar2 default ',') numero restituito;
END plsql_Delimited_String;
/

CREATE O SOSTITUITE IL CORPO DEL PACCHETTO plsql_Delimited_String
IS
FUNCTION Counter (Source_string IN VARCHAR2,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
iModifier PLS_INTEGER :=0;
iOldSize PLS_INTEGER :=LENGTH (Source_string);
BEGIN
IF Unterminated
THEN
iModifier :=1;
FINE SE;

RETURN (iOldSize - LENGTH (REPLACE (Source_string, Delimiter)))
+ iModifier;
END Counter;

PROCEDURA PutString (Source_string IN OUT VARCHAR2,
String_to_add IN VARCHAR2,
Field_position IN NUMBER,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
IS
iStrLen PLS_INTEGER :=LENGTH (stringa_origine);
iStrFragLen PLS_INTEGER :=LENGTH (stringa_da_aggiungere);
iPtrStart PLS_INTEGER :=0;
iPtrEnd PLS_INTEGER :=0;
vcSepBuffer VARCHAR2 (2000);
iCounter PLS_INTEGER;
BEGIN
-- 1. è la stringa Zero Length?
IF iStrLen =0
THEN
IF Field_Position> 1
THEN
FOR iCounter IN 2 .. Field_Position
LOOP
vcSepBuffer :=vcSepBuffer || Delimitatore;
END LOOP;
END IF;

Source_string :=vcSepBuffer || Stringa_da_aggiungere;

SE NON non terminato
ALLORA
Stringa_sorgente :=Stringa_sorgente || Delimiter;
iStrLen :=LENGTH (Source_string);
END IF;
ELSE
-- 2. Gestisci stringhe non terminate
IF UnTerminated
THEN
Stringa_sorgente :=Stringa_sorgente || Delimitatore;
END IF;

-- 3. Individua l'ennesimo separatore
IF Field_Position> 1
THEN
LOOP
iPtrStart :=
(INSTR (Source_string || vcSepBuffer,
Delimitatore,
1,
Field_Position - 1)
- 1)
+ LENGTH (Delimiter);
EXIT WHEN iPtrStart> 0;
vcSepBuffer :=vcSepBuffer || Delimitatore;
END LOOP;

SE vcSepBuffer NON È NULL
ALLORA
iPtrEnd :=iStrLen;
ELSE
iPtrEnd :=
INSTR (Source_string,
Delimiter,
1 ,
Posizione_campo);

IF iPtrEnd =0
THEN
iPtrEnd :=iStrLen;
END IF;
END IF;
ELSE
iPtrStart :=0;
iPtrEnd :=
INSTR (Source_string,
Delimiter,
1,
Field_Position);

IF iPtrEnd =0
THEN
iPtrEnd :=iStrLen;
END IF;
END IF;

-- 3. Ricompila la stringa
Source_string :=
SUBSTR (Source_string, 1, iPtrStart)
|| vcSepBuffer
|| Stringa_da_aggiungere
|| Delimitatore
|| SUBSTR (stringa_sorgente, iPtrEnd + LENGTH (delimitatore));

-- 4. Riordinare la terminazione
IF UnTerminated
THEN
Stringa_sorgente :=
SUBSTR (Stringa_origine,
1,
(LUNGHEZZA (stringa_origine) - LUNGHEZZA (Delimitatore)));
END IF;
END IF;
END PutString;

PROCEDURA PutNumber (Source_string IN OUT VARCHAR2,
number_to_add IN NUMBER,
Field_position IN NUMBER,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimitatore IN VARCHAR2 DEFAULT ',')
IS
BEGIN
-- 1. Esegui semplicemente conversioni di tipo di dati e chiama la varchar2 varsion di put..
plsql_Delimited_String.PutString (Source_string,
TO_CHAR (number_to_add),
Field_position,
UnTerminated,
Delimiter);
END PutNumber;

PROCEDURA PutDate (Source_string IN OUT VARCHAR2,
Date_to_add IN DATE,
Field_position IN NUMBER,
Non terminato IN BOOLEAN DEFAULT FALSE,
Delimitatore IN VARCHAR2 DEFAULT ',')
IS
BEGIN
-- 1. Esegui semplicemente conversioni di tipo di dati e chiama la varchar2 varsion di put..
plsql_Delimited_String.
PutString (Source_string,
TO_CHAR (date_to_add, ' DD-MON-YYYY HH24:MI:SS'),
Field_position,
UnTerminated,
Delimiter);
END PutDate;

FUNCTION GetString (Source_string IN VARCHAR2,
Field_position IN NUMBER,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
RETURN VARCHAR2
IS
iPtrEnd PLS_INTEGER :=0;
iPtrStart PLS_INTEGER :=0;
vcSourceStrCopy VARCHAR2 (2000) :=Source_string;
BEGIN
IF UnTerminated
THEN
vcSourceStrCopy :=vcSourceStrCopy || Delimitatore;
END IF;

IF Field_Position> 1
THEN
iPtrStart :=
INSTR (vcSourceStrCopy,
Delimiter,
1,
Field_Position - 1)
+ LENGTH (Delimitatore);
ELSE
iPtrStart :=1;
END IF;

iPtrEnd :=
INSTR (vcSourceStrCopy,
Delimiter,
1,
Field_Position);
RETURN SUBSTR (vcSourceStrCopy, iPtrStart, (iPtrEnd - iPtrStart));
FINE GetString; /* Versione stringa */

FUNCTION GetNumber (Source_string IN VARCHAR2,
Field_position IN NUMBER,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimitatore IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
iRc PLS_INTEGER;
BEGIN
RETURN TO_NUMBER (GetString (Source_string,
Field_Position,
UnTerminated,
Delimiter));
END GetNumber; /* Numero Versione */

FUNCTION GetDate (Source_string IN VARCHAR2,
Field_position IN NUMBER,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimitatore IN VARCHAR2 DEFAULT ',')
DATA DI RITORNO
IS
BEGIN
RETURN TO_DATE (GetString (Source_string,
Field_Position,
Unterminated,
Delimiter), 'DD-MON-YYYY HH24:MI:SS');
FINE GetDate; /* Data versione */

FUNCTION Locate (Source_string IN VARCHAR2,
Search_String IN VARCHAR2,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimitatore IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
iHit PLS_INTEGER :=0;
iCounter PLS_INTEGER;
vcCompare VARCHAR2 (2000);
BEGIN
FOR iCounter IN 1 .. Counter (Source_String, UnTerminated, Delimiter)
/> LOOP
IF GetString (Source_String,
iCounter,
UnTerminated,
Delimiter) =Search_String
THEN
iHit :=iCounter;
EXIT;
END IF;
END LOOP;

RETURN iHit;
END Individua;

FUNCTION Locate (Source_string IN VARCHAR2,
Search_date IN DATE,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimitatore IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
BEGIN
RETURN Individua (Source_string,
TO_CHAR (Search_date, 'DD-MON-YYYY HH24:MI:SS'),
UnTerminated,
Delimiter);
FINE Individua; /* Data versione */

FUNCTION Localizza (Source_string IN VARCHAR2,
Search_number IN NUMBER,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimitatore IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
BEGIN
RETURN Individua (Source_string,
TO_CHAR (Search_number),
Unterminated,
Delimitatore);
END Individua; /* Numero Versione */
END; /* Corpo */
/