Oracle
 sql >> Base de données >  >> RDS >> Oracle

Lire et importer efficacement des fichiers CSV dans Oracle PL/SQL

L'exemple est donné ci-dessous pour lire et importer un fichier CSV (séparé par des virgules) dans PLSQL. Il existe un package dans les formulaires Oracle "D2k_Delimited_String" que nous utilisons pour lire et importer un fichier délimité par des virgules (ou tout délimiteur), j'ai également écrit un article sur Oracle Forms pour lire des fichiers délimités avec ce package, voici le lien https:/ /www.foxinfotech.in/2013/02/reading-and-importing-comma-delimited.html. Le même package que j'ai converti en package de base de données pour lire efficacement le fichier CSV dans PLSQL, j'ai renommé le package en "Plsql_Delimited_String". L'exemple ci-dessous est donné pour importer un fichier csv dans PL SQL à l'aide de cette fonction de package Get_String, voici l'utilisation de cette fonction :

Plsql_Delimited_String.Getstring ([chaîne contenant du texte délimité, toute la ligne],
[occurrence],
[unterminated boolean default false],
[delimeter]);

Dans la procédure suivante, l'utilisateur transmettra un nom de fichier qui doit se trouver dans l'emplacement du répertoire créé dans l'objet de répertoire Oracle. Dans cet exemple, l'objet de répertoire "YOUR_DIRECTORY" est utilisé, modifiez-le avec votre objet de répertoire et copiez le fichier délimité à cet emplacement, puis passez le nom du fichier à cette procédure.

CRÉER OU REMPLACER LA PROCÉDURE Import_Emp_File (P_FILENAME IN VARCHAR2,
o_msg OUT VARCHAR2)
IS
Infile UTL_FILE.File_Type ;
Linebuf VARCHAR2 (4 000) ;
V_Getstring VARCHAR2 (100 );

-- Tableau des valeurs de champ
TYPE Fieldvalue IS TABLE OF VARCHAR2 (100)
INDEX BY BINARY_INTEGER ;

Field_Position Fieldvalue ;

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);
-- ajout d'un tuyau supplémentaire en fin de ligne pour lire tous les champs

BuffLigne :=BuffLigne || '|';

-- Supposons que le fichier contient six chaînes délimitées avec un tube (|)
FOR I IN 1 .. 6
LOOP
Field_Position (I) :=
Plsql_Delimited_String.Getstring (Linebuf ,
I,
FALSE,
'|');
END LOOP;

COMMENCER
Total_Rec_Count :=Total_Rec_Count + 1 ;

-- un exemple de tableau
INSERT INTO EMP (EMPLOYEE_NUMBER,
FIRST_NAME,
LAST_NAME,
DATE_OF_JOIN,
EMP_TYPE,
DATE_OF_REGN)
VALUES (position_champ (1),
position_champ (2),
position_champ (3),
position_champ (4),
position_champ (5),
position_champ (6) );

Total_Rec_Processed :=Total_Rec_Processed + 1 ;
EXCEPTION
WHEN OTHERS
THEN
-- erreur ignorée lors de l'insertion de la base de données
NULL ;
END ;
FIN DE BOUCLE ;

IF UTL_FILE.is_open (infile)
THEN
UTL_FILE.Fclose (infile);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
IF UTL_FILE.is_open (infile)
THEN
UTL_FILE.Fclose (infile);
END IF;

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

o_msg :=SQLERRM;
END;
/Ce qui suit est la source du package de PLSQL_DELIMITED_STRING utilisé dans cet exemple, installez ce package dans votre schéma. Le package contient de nombreuses autres fonctions utilitaires qui peuvent être utilisées pour lire le fichier csv à l'aide de PLSQL :

CRÉER OU REMPLACER LE PACKAGE plsql_Delimited_String IS

function Counter( Source_string in varchar2,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',') return number;
Procedure PutString( Source_string in out varchar2,
String_to_add in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',');
Procedure PutNumber( Source_string in out varchar2,
number_to_add in number,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',');
Procedure PutDate( Source_string in out varchar2,
Date_à_ajouter dans la date,
Field_position dans le nombre,
Non terminé dans Bo olean default FALSE,
Delimiter in varchar2 default ',');
function GetString( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Délimiteur dans varchar2 default ',') return varchar2;
function GetNumber( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ', ') return number;
function GetDate( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',') return date;
fonction Locate( Source_string dans varchar2,
Search_String dans varchar2,
UnTerminated dans Boole un FALSE par défaut,
Delimiter in varchar2 default ',') return number;
function Locate( Source_string in varchar2,
Search_date in date,
UnTerminated in Boolean default FALSE,
/> Délimiteur dans varchar2 default ',') return number ;
fonction Locate( Source_string in varchar2,
Search_number in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',') renvoie le numéro ;
END plsql_Delimited_String;
/

CREATE OR REMPLACE PACKAGE BODY plsql_Delimited_String
IS
FUNCTION Compteur (Source_string IN VARCHAR2,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
iModifier PLS_INTEGER :=0 ;
iOldSize PLS_INTEGER :=LENGTH (Source_string);
BEGIN
IF Unterminé
THEN
iModifier :=1;
FIN SI;

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

PROCEDURE PutString (Source_string IN OUT VARCHAR2,
String_to_add IN VARCHAR2,
Field_position IN NUMBER,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
IS
iStrLen PLS_INTEGER :=LONGUEUR (chaîne_source) ;
iStrFragLen PLS_INTEGER :=LONGUEUR (chaîne_à_ajouter );
iPtrStart PLS_INTEGER :=0 ;
iPtrEnd PLS_INTEGER :=0 ;
vcSepBuffer VARCHAR2 (2000);
iCounter PLS_INTEGER;
BEGIN
-- 1. la chaîne est-elle de longueur nulle ?
IF iStrLen =0
THEN
IF Field_Position> 1
THEN
FOR iCounter IN 2 .. Field_Position
LOOP
vcSepBuffer :=vcSepBuffer || Délimiteur ;
END LOOP ;
END IF ;

Chaîne_source :=vcSepBuffer || Chaîne_à_ajouter ;

IF NOT UnTerminated
THEN
Source_string :=Source_String || Delimiter ;
iStrLen :=LENGTH (Source_string);
END IF;
ELSE
-- 2. Gérer les chaînes non terminées
IF UnTerminated
THEN
Chaîne_source :=Chaîne_source || Délimiteur ;
FIN SI ;

-- 3. Localisez le nième-1 séparateur
IF Field_Position> 1
THEN
LOOP
iPtrStart :=
(INSTR (Source_string || vcSepBuffer,
Delimiter,
1,
Field_Position - 1)
- 1)
+ LENGTH (Delimiter);
EXIT WHEN iPtrStart> 0;
vcSepBuffer :=vcSepBuffer || Délimiteur ;
FIN DE BOUCLE ;

IF vcSepBuffer IS NOT NULL
THEN
iPtrEnd :=iStrLen;
ELSE
iPtrEnd :=
INSTR (Source_string,
Delimiter,
1 ,
Field_Position);

SI iPtrFin =0
ALORS
iPtrFin :=iStrLen;
FIN SI;
FIN SI;
SINON
iPtrDébut :=0;
iPtrEnd :=
INSTR (Source_string,
Delimiter,
1,
Field_Position);

SI iPtrFin =0
ALORS
iPtrFin :=iStrLen;
FIN SI;
FIN SI;

-- 3. Reconstruire la chaîne
Source_string :=
SUBSTR (Source_string, 1, iPtrStart)
|| vcSepBuffer
|| Chaîne_à_ajouter
|| Délimiteur
|| SUBSTR (Source_string, iPtrEnd + LENGTH (Delimiter));

-- 4. Trier la terminaison
IF UnTerminated
THEN
Source_string :=
SUBSTR (Source_String,
1,
(LENGTH (Source_string) - LENGTH (Délimiteur)));
END IF;
END IF;
END PutString;

PROCÉDURE PutNumber (chaîne_source IN OUT VARCHAR2,
nombre_à_ajouter IN NUMBER,
Field_position IN NUMBER,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
IS
COMMENCEZ
-- 1. Effectuez simplement des conversions de type de données et appelez la variante varchar2 de put..
plsql_Delimited_String.PutString (Source_string,
TO_CHAR (number_to_add),
Field_position,
Non terminé,
Delimiter);
END PutNumber;

PROCEDURE PutDate (Source_string IN OUT VARCHAR2,
Date_to_add IN DATE,
Field_position IN NUMBER,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
IS
COMMENCEZ
-- 1. Effectuez simplement des conversions de type de données et appelez la varsion varchar2 de put..
plsql_Delimited_String.
PutString (Source_string,
TO_CHAR (date_to_add, ' DD-MON-YYYY HH24:MI:SS'),
Field_position,
Non terminé,
Delimiter);
END PutDate;

FUNCTION GetString (Source_string IN VARCHAR2,
Field_position IN NUMBER,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
RETURN VARCHAR2
IS
iPtrEnd PLS_INTEGER :=0;
iPtrStart PLS_INTEGER :=0;
vcSourceStrCopy VARCHAR2 (2000) :=Source_string;
COMMENCER
SI UnTerminated
ALORS
vcSourceStrCopy :=vcSourceStrCopy || Délimiteur ;
FIN SI ;

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

iPtrEnd :=
INSTR (vcSourceStrCopy,
Delimiter,
1,
Field_Position);
RETURN SUBSTR (vcSourceStrCopy, iPtrStart, (iPtrEnd - iPtrStart));
FIN GetString ; /* Version de la chaîne */

FUNCTION GetNumber (Source_string IN VARCHAR2,
Field_position IN NUMBER,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
NUMÉRO DE RETOUR
IS
iRc PLS_INTEGER ;
BEGIN
RETURN TO_NUMBER (GetString (Source_string,
Field_Position,
UnTerminated,
Delimiter));
END GetNumber ; /* Numéro de version */

FUNCTION GetDate (Source_string IN VARCHAR2,
Field_position IN NUMBER,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
RETURN DATE
IS
BEGIN
RETURN TO_DATE (GetString (Source_string,
Field_Position,
Unterminated,
Delimiter), 'DD-MON-YYYY HH24:MI:SS');
FIN GetDate ; /* Version de date */

FUNCTION Locate (Source_string IN VARCHAR2,
Search_String IN VARCHAR2,
Non terminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
NUMÉRO DE RETOUR
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;
SORTIE ;
FIN SI ;
FIN BOUCLE ;

RETURN iHit;
FIN Localiser;

FUNCTION Locate (Source_string IN VARCHAR2,
Search_date IN DATE,
Unterminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
NUMÉRO DE RETOUR
EST
/> BEGIN
RETURN Locate (Source_string,
TO_CHAR (Search_date, 'DD-MON-YYYY HH24:MI:SS'),
UnTerminated,
Delimiter);
FIN Localiser ; /* Version de date */

FUNCTION Locate (Source_string IN VARCHAR2,
Search_number IN NUMBER,
Unterminé IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
NUMÉRO DE RETOUR
IS
BEGIN
RETURN Locate (Source_string,
TO_CHAR (Search_number),
UnTerminated,
Delimiter);
END Locate; /* Numéro de version */
END ; /* Corps */
/