Immer wieder kommt die Frage, wie man CSV-Dateien via PL/SQL importieren kann, wenn man keinen Zugriff auf das Dateiverzeichnis des Datenbankservers hat. Ich habe in diesem Artikel ein Beispiel vorbereitet, das die grundlegende Vorgehensweise darstellt und leicht an die individuellen Bedürfnisse angepasst werden kann. Dieses Beispiel liest Zeitbuchungen verschiedener Terminals und importiert diese in die dafür vorgesehene Importtabelle MDZEIMP. Die Funktion enthält ein BLOB als Input-Parameter, welches vom Client übergeben wird.
CREATE OR REPLACE PROCEDURE Ind_ImportCSV(theFile IN BLOB) IS
sourceCharSet VARCHAR2(40) := 'AL32UTF8';
dbCharSet VARCHAR2(40) := Md_Sql.GetDBCharSet;
m_File UTL_FILE.FILE_TYPE;
theLine VARCHAR2(200);
isFirst BOOLEAN := true;
rec mdzeimp%ROWTYPE;
BEGIN
-- create an oracle directory 'IMPORT' first
Md_Lib.WriteBlobToFile(Md_Zip.UnzipBlob(theFile), 'IMPORT', 'Imp_ZE.csv');
m_File := UTL_FILE.FOPEN ('IMPORT', 'Imp_ZE.csv', 'r', 200);
-- sets the default delimiter of the CSV file
Md_ImpLieItm.SetDelimiter(';');
loop
begin
theLine := NULL;
UTL_FILE.GET_LINE (m_File, theLine);
if (TRIM(theLine) is null) then
exit;
end if;
exception
when NO_DATA_FOUND then
exit;
end;
if (isFirst) then
-- ignore header line
isFirst := false;
else
--Card_Nr;time;Come/Go;Device_ID
--1046;04.01.2016 07:05;G;5
--activate this line when to convert to a different charset
--theLine := CONVERT(theLine, dbCharSet, sourceCharSet);
rec.Card_Nr := Md_ImpLieItm.Extract(theLine);
rec.StartTime := TO_DATE(Md_ImpLieItm.Extract(theLine), 'DD.MM.YYYY HH24:MI');
rec.Zea_Code := Md_ImpLieItm.Extract(theLine);
rec.Terminal := TO_NUMBER(Md_ImpLieItm.Extract(theLine));
rec.Terminal_Type := 'FP';
insert into mdzeimp values rec;
end if;
end loop;
commit;
UTL_FILE.FCLOSE(m_File);
exception
when OTHERS then
if (UTL_FILE.IS_OPEN (m_File)) then UTL_FILE.FCLOSE(m_File); end if;
Md_Error.Raise;
END;
/
Die BLOB-Datei wird zuerst im Oracle-Verzeichnis 'IMPORT' gespeichert (dieses muss vorher angelegt werden falls noch nicht vorhanden). Danach wird mit UTL_FILE jede Zeile einzeln gelesen und verarbeitet. Mit Hilfe des Packages Md_ImpLieItem werden die Felder der CSV-Datei extrahiert und den Feldern der Tabelle zugewiesen.
Was jetzt noch fehlt ist das entsprechende Command für das Hochladen der CSV-Datei, das wir direkt im Hauptmenü des HRM-Moduls platzieren. Daher definieren wir dieses Command im XML-Repository der Datei RBI_PREMIUM#EXTENSION:
<?xml version="1.0"?>
<ResourceBundleInfoContainer xmlns:mdc="http://www.multidata.at/mp5/Common" xmlns="http://www.multidata.at/mp5" >
<CommandsCatalog>
<Command Name="Ind.ZeUpload" Title="Upload terminal data" Mode="DbCall" Action="Ind_ImportCSV">
<Parameters>
<mdc:Parameter Name="theFile" DataType="Blob" Title="File" Value="D:\Temp\Terminal.csv" Display="true"/>
</Parameters>
</Command>
</CommandsCatalog>
<MenusCatalog>
<MenuBarItem Title="Zeiterfass&ung">
<MenuBarItem Title="Importe">
<MenuBarItem CommandName="Ind.ZeUpload" BeginGroup="true" />
</MenuBarItem>
</MenuBarItem>
</MenusCatalog>
</ResourceBundleInfoContainer>