prog:oracle_apex_5_file_handling
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
prog:oracle_apex_5_file_handling [2018/07/30 12:20] – [Code für den Page Submit Process] gpipperr | prog:oracle_apex_5_file_handling [2019/10/28 12:33] (aktuell) – gpipperr | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | =====Oracle APEX 5 - Dateien laden und parsen===== | ||
+ | **07/2018** | ||
+ | |||
+ | <fc # | ||
+ | |||
+ | Eine CSV Datein in Apex per Weboberfläche laden und in der DB weiter verarbeiten | ||
+ | |||
+ | < | ||
+ | |||
+ | |||
+ | ==== Wie lädt Oracle Apex Dateien? ==== | ||
+ | |||
+ | Im Standard lädt Oracle APEX 5 Dateien temporär die die Tabelle **apex_application_temp_files**, | ||
+ | |||
+ | In der Seite mit dem Page Item "File Browse" | ||
+ | |||
+ | Details zu den Fähigkeiten von "File Browse" | ||
+ | |||
+ | D.h. die hoch geladenen Daten müsse für die Weiterverarbeitung aus dieser Tabelle exportiert , weiter kopiert werden. Die Datei kann dazu in der Tabelle über den Dateinamen gefunden werden. | ||
+ | |||
+ | Zum Beispiel für eine einzelne Datei: | ||
+ | |||
+ | <code plsql> | ||
+ | .. | ||
+ | | ||
+ | into v_file_count | ||
+ | from apex_application_temp_files | ||
+ | where name = : | ||
+ | if v_file_count > 0 | ||
+ | then | ||
+ | -- Read data from apex_application_temp_files | ||
+ | | ||
+ | into v_blob_data | ||
+ | from apex_application_temp_files | ||
+ | where name = : | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | |||
+ | |||
+ | ==== Mit dem Oracle APEX Data Loader ==== | ||
+ | |||
+ | |||
+ | Über den Page Wizard lässt sich ein komfortabler und einfach zu bedienender Data Loader erstellen. | ||
+ | |||
+ | Siehe dazu aus der Online Doku: http:// | ||
+ | |||
+ | |||
+ | |||
+ | Fazit: Schöner Wizard mit guten Funktionen, ABER => nur für kleine Dateien geeignet, bei 10MB Dateien ist bereits Schluss. | ||
+ | |||
+ | Das liegt aber auch an der Konfiguration der Apex Umgebung (Speicher!!), | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Eigenbau Lösung für Images ==== | ||
+ | |||
+ | Siehe dazu ausführlich hier => [[prog: | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Eigenbau Lösung für CSV Dateien ==== | ||
+ | |||
+ | Da im aktuellen Projekt schnell eine robustere Lösung für das Laden von CSV Datein gefunden werden muss, nach ein paar Ideen im Internet gesucht. | ||
+ | |||
+ | Danke für die ersten Iden von [[ https:// | ||
+ | |||
+ | Ziel ist es eine beliebige CSV Tabelle in eine Stage Tabelle mit 30 Spalten zu laden, die ersten 30 Spalten werden dabei bei der CSV Datei in die Tabelle geschrieben. | ||
+ | |||
+ | Die Daten können auch Separator Zeichen enthalten, das heißt wenn ein Text mit "" | ||
+ | |||
+ | |||
+ | === Ablauf === | ||
+ | |||
+ | * Leere Seite anlegen - in meine Fall mit der ID 3100 | ||
+ | * ITEM vom Typ "File Browse" | ||
+ | * Button für den Submit hinzufügen | ||
+ | * Process mit dem PL/SQL Code anlegen | ||
+ | |||
+ | |||
+ | ===Code für den Page Submit Process === | ||
+ | |||
+ | |||
+ | Ein Erster Test mit Lesen der Datei zeichen bei Zeichen war nicht erfolgreich, | ||
+ | |||
+ | Daher zerlege ich die Datei in einzelne Zeilen und verarbeitete dann die Zeilen. | ||
+ | |||
+ | <code plsql upload_apex.sql> | ||
+ | declare | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | -- | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | return clob | ||
+ | as | ||
+ | v_clob | ||
+ | v_dest_offset | ||
+ | v_src_offset | ||
+ | v_lang_context | ||
+ | v_warning | ||
+ | begin | ||
+ | dbms_lob.CREATETEMPORARY(v_clob, | ||
+ | |||
+ | |||
+ | |||
+ | dbms_lob.converttoclob(v_clob | ||
+ | ,p_blob_in | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | |||
+ | return v_clob; | ||
+ | end convertToClob; | ||
+ | |||
+ | -- get the runtime information | ||
+ | | ||
+ | return number | ||
+ | is | ||
+ | | ||
+ | | ||
+ | | ||
+ | v_Seconds | ||
+ | begin | ||
+ | -- get the runtime of the load process | ||
+ | v_endtime := systimestamp; | ||
+ | v_runtime := v_endtime - p_starttime; | ||
+ | |||
+ | select | ||
+ | + extract(hour from v_runtime) * 3600 | ||
+ | + extract(minute from v_runtime) * 60 | ||
+ | + extract(second from v_runtime) | ||
+ | into v_Seconds | ||
+ | from dual; | ||
+ | |||
+ | | ||
+ | |||
+ | end getRunTime ; | ||
+ | |||
+ | begin | ||
+ | -- check if parameter exits | ||
+ | if : | ||
+ | then | ||
+ | v_charset := nvl( : | ||
+ | v_message := | ||
+ | v_message | ||
+ | || ' Start load import file ' | ||
+ | || : | ||
+ | || ' <br/> with the charset ' | ||
+ | || :P1_CHARSET | ||
+ | || '< | ||
+ | |||
+ | -- check if the file exits | ||
+ | select count(ID) | ||
+ | into v_file_count | ||
+ | from apex_application_temp_files | ||
+ | where name = : | ||
+ | |||
+ | -- check if the upload was sucessfull | ||
+ | if v_file_count > 0 | ||
+ | then | ||
+ | | ||
+ | -- clean the local stage table | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | -- Read data from apex_application_temp_files | ||
+ | | ||
+ | into v_blob_data, | ||
+ | from apex_application_temp_files | ||
+ | where name = : | ||
+ | |||
+ | -- read the data into a clob | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | v_message || ' Read ' || to_char(v_blob_len) || ' byte and ' || to_char(v_clob_len) || ' characters < | ||
+ | | ||
+ | -- check again if stage table is empty | ||
+ | -- check that this table is empty | ||
+ | | ||
+ | |||
+ | if v_rec_count > 0 then | ||
+ | RAISE_APPLICATION_ERROR | ||
+ | end if; | ||
+ | |||
+ | -- parse the file | ||
+ | | ||
+ | loop | ||
+ | |||
+ | -- use bigger chunks to avoid problem with substr | ||
+ | -- reading on be one is to with DBMS_LOB.substr is very slow! | ||
+ | | ||
+ | v_line_end_pos: | ||
+ | | ||
+ | -- if v_line_end_pos is 0 then throw exception | ||
+ | -- | ||
+ | if v_line_end_pos = 0 then | ||
+ | raise_application_error( -20001 , '-- Error :: Can not upload CSV files with linesize >> | ||
+ | end if; | ||
+ | | ||
+ | v_chunk_len: | ||
+ | | ||
+ | v_line := dbms_lob.substr(v_clob_data , v_chunk_len, | ||
+ | |||
+ | -- auf die nächste Position weiterschalten | ||
+ | v_position := v_position + v_chunk_len; | ||
+ | |||
+ | -- v_message := | ||
+ | -- v_message | ||
+ | -- || ' DEBUG v_line_end_pos::' | ||
+ | |||
+ | -- get the lenght | ||
+ | v_l := length(v_line); | ||
+ | |||
+ | -- read the string | ||
+ | for i in 1 .. v_l | ||
+ | loop | ||
+ | v_rchar := substr(v_line, | ||
+ | |||
+ | if v_rchar ='"' | ||
+ | | ||
+ | end if; | ||
+ | if v_rchar =v_char_sperator and v_rbefore='"' | ||
+ | | ||
+ | end if; | ||
+ | |||
+ | if v_rchar =v_char_sperator and v_match | ||
+ | then | ||
+ | | ||
+ | end if; | ||
+ | v_rbefore: | ||
+ | | ||
+ | end loop; | ||
+ | |||
+ | -- replace all " | ||
+ | v_line := replace(v_line, | ||
+ | |||
+ | -- Convert comma to : to use the wwv_flow_utilities | ||
+ | v_line := replace(v_line, | ||
+ | |||
+ | -- get ',' | ||
+ | v_line := replace(v_line, | ||
+ | |||
+ | -- Convert each column separated by : into array of data </ | ||
+ | v_data_array := wwv_flow_utilities.string_to_table(v_line); | ||
+ | |||
+ | -- fill the missing records to get the 30 values | ||
+ | for y in 1 .. 30 | ||
+ | loop | ||
+ | if v_data_array.exists(y) | ||
+ | then | ||
+ | null; | ||
+ | else | ||
+ | -- I use this strange sign to filter out the data later in this ETL process | ||
+ | | ||
+ | --debug | ||
+ | --v_data_array(29) := v_mime_type; | ||
+ | end if; | ||
+ | end loop; | ||
+ | |||
+ | -- insert into the stage table DWH_OPERATION.COMET_CONTRACT_INPUT3@DEDWHOPERATION | ||
+ | | ||
+ | , | ||
+ | ,FIELD01 | ||
+ | ,FIELD02 | ||
+ | ,FIELD03 | ||
+ | ,FIELD04 | ||
+ | ,FIELD05 | ||
+ | ,FIELD06 | ||
+ | ,FIELD07 | ||
+ | ,FIELD08 | ||
+ | ,FIELD09 | ||
+ | ,FIELD10 | ||
+ | ,FIELD11 | ||
+ | ,FIELD12 | ||
+ | ,FIELD13 | ||
+ | ,FIELD14 | ||
+ | ,FIELD15 | ||
+ | ,FIELD16 | ||
+ | ,FIELD17 | ||
+ | ,FIELD18 | ||
+ | ,FIELD19 | ||
+ | ,FIELD20 | ||
+ | ,FIELD21 | ||
+ | ,FIELD22 | ||
+ | ,FIELD23 | ||
+ | ,FIELD24 | ||
+ | ,FIELD25 | ||
+ | ,FIELD26 | ||
+ | ,FIELD27 | ||
+ | ,FIELD28 | ||
+ | ,FIELD29 | ||
+ | ,FIELD30) | ||
+ | values (v_sr_no | ||
+ | ,: | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | , | ||
+ | |||
+ | |||
+ | -- reset line | ||
+ | | ||
+ | -- rember line count | ||
+ | | ||
+ | |||
+ | if mod(v_sr_no, | ||
+ | then | ||
+ | commit; | ||
+ | end if; | ||
+ | |||
+ | -- free the collecio | ||
+ | | ||
+ | | ||
+ | end loop; | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | || ' rows after '|| to_char(v_Seconds, | ||
+ | || ' Seconds</ | ||
+ | |||
+ | |||
+ | | ||
+ | else | ||
+ | | ||
+ | end if; | ||
+ | end if; | ||
+ | |||
+ | -- get the runtime of the load process | ||
+ | -- get the runtime of the load process | ||
+ | -- | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | exception | ||
+ | when others | ||
+ | then | ||
+ | v_message := v_message || ' ' || sqlerrm; | ||
+ | apex_application.g_print_success_message := '< | ||
+ | end; | ||
+ | </ | ||
+ | |||
+ | Um nun mit dem Upload Pattern eine richtige XLS Datei zu verarbeiten ist dann wohl dieser Code dienlich => https:// | ||
+ | |||
+ | ---- | ||
+ | |||
+ | |||
+ | ==== Wieder als CSV auslesen ==== | ||
+ | siehe => [[prog: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Quellen ==== | ||
+ | |||
+ | |||
+ | * https:// | ||
+ | |||
+ | |||
+ | HEX | ||
+ | * http:// |
prog/oracle_apex_5_file_handling.txt · Zuletzt geändert: 2019/10/28 12:33 von gpipperr