Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Effizientes Lesen und Importieren von CSV-Dateien in Oracle PL/SQL

Das folgende Beispiel zeigt das Lesen und Importieren von CSV-Dateien Datei (kommagetrennt) in PLSQL. Es gibt ein Paket in Oracle-Formularen "D2k_Delimited_String", das wir zum Lesen und Importieren von durch Kommas (oder beliebige Trennzeichen) getrennten Dateien verwenden. /www.foxinfotech.in/2013/02/reading-and-importing-comma-delimited.html. Das gleiche Paket, das ich in ein Datenbankpaket konvertiert habe, um die CSV-Datei in PLSQL effizient zu lesen, habe ich das Paket in "Plsql_Delimited_String" umbenannt. Nachfolgend finden Sie ein Beispiel für den Import einer CSV-Datei in PL SQL mit Hilfe dieser Paketfunktion Get_String. Im Folgenden wird die Verwendung dieser Funktion beschrieben:

Plsql_Delimited_String.Getstring ([String mit begrenztem Text, die ganze Zeile],
[Vorkommen],
[unterbrochener boolescher Standardwert falsch],
[Trennzeichen]);

In der folgenden Prozedur übergibt der Benutzer einen Dateinamen, der sich an dem im Oracle-Verzeichnisobjekt erstellten Verzeichnisort befinden sollte. In diesem Beispiel wird das Verzeichnisobjekt „YOUR_DIRECTORY“ verwendet. Ändern Sie ihn mit Ihrem Verzeichnisobjekt und kopieren Sie die Datei mit Trennzeichen an diesen Ort und übergeben Sie sie dann der Dateiname für diese Prozedur.

CREATE OR REPLACE PROCEDURE Import_Emp_File (P_FILENAME IN VARCHAR2,
o_msg OUT VARCHAR2)
IST
Infile UTL_FILE.File_Type;
Linebuf VARCHAR2 (4000);
V_Getstring VARCHAR2 (100 );

-- Feldwerte-Array
TYPE Feldwert IS TABLE OF VARCHAR2 (100)
INDEX BY BINARY_INTEGER;

Field_Position Feldwert;

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);
-- Hinzufügen einer zusätzlichen Pipe am Ende der Zeile, um alle Felder zu lesen

Linebuf :=Linebuf || '|';

-- Angenommen, die Datei enthält sechs getrennte Zeichenfolgen mit Pipe (|)
FOR I IN 1 .. 6
LOOP
Field_Position (I) :=
Plsql_Delimited_String.Getstring (Linebuf ,
I,
FALSE,
'|');
END LOOP;

BEGIN
Total_Rec_Count :=Total_Rec_Count + 1;

-- eine Beispieltabelle
INSERT INTO EMP (EMPLOYEE_NUMBER,
FIRST_NAME,
LAST_NAME,
DATE_OF_JOIN,
EMP_TYPE,
DATE_OF_REGN)
VALUES (Feldposition (1),
Feldposition (2),
Feldposition (3),
Feldposition (4),
Feldposition (5),
Feldposition (6) );

Total_Rec_Processed :=Total_Rec_Processed + 1;
EXCEPTION
WHEN OTHERS
THEN
-- Fehler beim Einfügen in die Datenbank wird ignoriert
NULL;
END;
SCHLEIFE ENDE;

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;
/Das Folgende ist die Paketquelle von PLSQL_DELIMITED_STRING, die in diesem Beispiel verwendet wird, installieren Sie dieses Paket in Ihrem Schema. Das Paket enthält viele andere Hilfsfunktionen, die zum Lesen der CSV-Datei mit PLSQL verwendet werden können:

PAKET ERSTELLEN ODER ERSETZEN 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 Zahl,
Feld_Position in Zahl,
Unterminiert in Boolean, Standard FALSE,
Trennzeichen in Varchar2, Standard ',');
Prozedur PutDate( Source_string in Out Varchar2,
Date_to_add in date,
Field_position in number,
UnTerminated in Bo olean default FALSE,
Trennzeichen in varchar2 default ',');
function GetString( Source_string in varchar2,
field_position in number,
UnTerminated in boolean default FALSE,
Delimiter in varchar2 default ',') return varchar2;
function GetNumber( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ', ') Nummer zurückgeben;
function GetDate( Source_string in varchar2,
Field_position in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',') return date;
function Locate( Source_string in varchar2,
Search_String in varchar2,
UnTerminated in Boole ein Standard FALSE,
Trennzeichen in varchar2 Standard ',') Rückgabenummer;
Funktion Locate( Source_string in varchar2,
Search_date in date,
UnTerminated in Boolean default FALSE,
/> Trennzeichen in varchar2 default ',') Zahl zurückgeben;
function Locate( Source_string in varchar2,
Search_number in number,
UnTerminated in Boolean default FALSE,
Delimiter in varchar2 default ',') Rückgabenummer;
END plsql_Delimited_String;
/

PAKETKÖRPER ERSTELLEN ODER ERSETZEN plsql_Delimited_String
IS
FUNKTION Zähler (Quellzeichenfolge IN VARCHAR2,
Unterminiert IN BOOLEAN DEFAULT FALSE,
Trennzeichen IN VARCHAR2 DEFAULT ',')
RÜCKGABENUMMER
IS
iModifier PLS_INTEGER :=0;
iOldSize PLS_INTEGER :=LENGTH (Source_string);
BEGIN
IF Unterminated
THEN
iModifier :=1;
END IF;

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

VERFAHREN PutString (Quellstring 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 (Source_String);
iStrFragLen PLS_INTEGER :=LENGTH (String_to_add);
iPtrStart PLS_INTEGER :=0;
iPtrEnd PLS_INTEGER :=0;
vcSepBuffer VARCHAR2 (2000);
iCounter PLS_INTEGER;
BEGIN
-- 1. ist die Zeichenfolge Nulllänge?
IF iStrLen =0
THEN
IF Field_Position> 1
THEN
FOR iCounter IN 2 .. Field_Position
LOOP
vcSepBuffer :=vcSepBuffer || Trennzeichen;
END LOOP;
END IF;

Quellzeichenfolge :=vcSepBuffer || String_to_add;

IF NOT UnTerminated
THEN
Source_string :=Source_String || Delimiter;
iStrLen :=LENGTH (Source_string);
END IF;
ELSE
-- 2. Umgang mit nicht beendeten Strings
IF UnTerminated
THEN
Quellzeichenfolge :=Quellzeichenfolge || Trennzeichen;
END IF;

-- 3. Suchen Sie das n-te Trennzeichen
IF Field_Position> 1
THEN
LOOP
iPtrStart :=
(INSTR (Source_string || vcSepBuffer,
Trennzeichen,
1,
Field_Position - 1)
- 1)
+ LENGTH (Trennzeichen);
EXIT WHEN iPtrStart> 0;
vcSepBuffer :=vcSepPuffer || Trennzeichen;
END LOOP;

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

IF iPtrEnd =0
THEN
iPtrEnd :=iStrLen;
END IF;
END IF;
ELSE
iPtrStart :=0;
iPtrEnd :=
INSTR (Quellzeichenfolge,
Trennzeichen,
1,
Feldposition);

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

-- 3. Erstellen Sie den String neu
Source_string :=
SUBSTR (Source_string, 1, iPtrStart)
|| vcSepBuffer
|| String_to_add
|| Trennzeichen
|| SUBSTR (Quellzeichenfolge, iPtrEnd + LENGTH (Trennzeichen));

-- 4. Terminierung aussortieren
IF UnTerminated
THEN
Source_string :=
SUBSTR (Source_String,
1,
(LENGTH (Source_string) - LENGTH (Trennzeichen)));
END IF;
END IF;
END PutString;

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 ',')
IS
BEGIN
-- 1. Führen Sie einfach Datentypkonvertierungen durch und rufen Sie die varchar2-Variante von put auf..
plsql_Delimited_String.PutString (Source_string,
TO_CHAR (number_to_add),
Field_position,
Unterminated,
Delimiter);
END PutNumber;

PROCEDURE PutDate (Source_string IN OUT VARCHAR2,
Date_to_add IN DATE,
Field_position IN NUMBER,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
IS
BEGIN
-- 1. Führen Sie einfach Datentypkonvertierungen durch und rufen Sie die varchar2-Variante von put auf..
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 || Trennzeichen;
END IF;

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

iPtrEnd :=
INSTR (vcSourceStrCopy,
Delimiter,
1,
Field_Position);
RETURN SUBSTR (vcSourceStrCopy, iPtrStart, (iPtrEnd - iPtrStart));
ENDE GetString; /* Zeichenfolgenversion */

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

FUNCTION GetDate (Source_string IN VARCHAR2,
Field_position IN NUMBER,
Unterminated 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');
ENDE GetDate; /* Datum Version */

FUNCTION Locate (Source_string IN VARCHAR2,
Search_String IN VARCHAR2,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimiter 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 Locate;

FUNCTION Locate (Source_string IN VARCHAR2,
Search_date IN DATE,
Unterminated IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
BEGIN
RETURN Locate (Source_string,
TO_CHAR (Search_date, 'DD-MON-YYYY HH24:MI:SS'),
Unterminated,
Delimiter);
ENDE Suchen; /* Datum Version */

FUNCTION Locate (Source_string IN VARCHAR2,
Search_number IN NUMBER,
UnTerminated IN BOOLEAN DEFAULT FALSE,
Delimiter IN VARCHAR2 DEFAULT ',')
RETURN NUMBER
IS
BEGIN
RETURN Locate (Source_string,
TO_CHAR (Search_number),
Unterminated,
Delimiter);
END Locate; /* Versionsnummer */
ENDE; /* Körper */
/