Skip to main content

Behind The Scene of Processing CSV in Oracle Database using PL/SQL

Melanjutkan postingan sebelumnya: Memproses CSV yg di upload menggunakan APEX dimana penjelasan back end process dan behind the scene Saya coba paparkan semudah mungkin.

Langkah-langkah mengkonversi konten CSV menjadi baris-baris tabel di Oracle Database bisa dilakukan dengan tahapan berikut init.

Pasang dulu 2 fungsi yang sangat dibutuhkan yaitu:
  • Fungsi F_CSV_CONVERT_TO_TABLE
  • Fungsi HEX_TO_DECIMAL

Fungsi F_CSV_CONVERT_TO_TABLE (Detail)
CREATE OR REPLACE FUNCTION "F_CSV_CONVERT_TO_TABLE"
( p_in_string IN VARCHAR2
, p_in_encapsulator IN VARCHAR2 DEFAULT '"'
)
RETURN wwv_flow_global.vc_arr2
AS
l_string VARCHAR2(32767) := p_in_string || ',';
l_quote_start_index PLS_INTEGER := 0;
l_quote_end_index PLS_INTEGER := 0;
l_comma_index PLS_INTEGER;
l_index PLS_INTEGER := 1;
l_tab wwv_flow_global.vc_arr2;
i PLS_INTEGER := 1;
BEGIN
LOOP
l_comma_index := REGEXP_INSTR(l_string, '[,'||p_in_encapsulator||']', l_index);
EXIT WHEN l_comma_index = 0;

CASE
WHEN SUBSTR(l_string,l_comma_index,1) = p_in_encapsulator AND l_quote_start_index = 0 THEN
l_quote_start_index := l_comma_index;
WHEN SUBSTR(l_string,l_comma_index,1) = p_in_encapsulator AND l_quote_start_index <> 0 THEN
l_quote_end_index := l_comma_index;
ELSE
NULL;
END CASE;

IF l_quote_start_index = 0 THEN

l_tab(i) := SUBSTR(l_string, l_index, l_comma_index - l_index);
i := i+1;

ELSIF l_quote_start_index <> 0 AND l_quote_end_index <> 0 THEN

l_tab(i) := SUBSTR(l_string, l_quote_start_index+1, (l_quote_end_index - l_quote_start_index)-1);
i := i+1;
--
-- Lets reset our quote check
--
l_quote_start_index := 0;
l_quote_end_index := 0;
--
-- We need to discard our end comma
--
l_comma_index := INSTR(l_string, ',', l_index);
END IF;Fungsi HEX_TO_DECIMAL
l_index := l_comma_index + 1;
END LOOP;
RETURN l_tab;
END f_csv_convert_to_table;

Fungsi HEX_TO_DECIMAL (Detail)
CREATE OR REPLACE FUNCTION "HEX_TO_DECIMAL"
--this function is based on one by Connor McDonald
--http://www.jlcomp.demon.co.uk/faq/base_convert.html
( p_hex_str in varchar2 ) return number
is
v_dec number;
v_hex varchar2(16) := '0123456789ABCDEF';
begin
v_dec := 0;
for indx in 1 .. length(p_hex_str)
loop
v_dec := v_dec * 16 + instr(v_hex,upper(substr(p_hex_str,indx,1)))-1;
end loop;
return v_dec;
end hex_to_decimal;


Process Handler yang dipasang pada salah satu APEX page seperti pada gambar dibawah ini (event tombol "Finish" diklik):

detail prosesnya adalah sbb:
declare
l_mime_type APEX_APPLICATION_FILES.mime_type%type;
l_doc_size APEX_APPLICATION_FILES.doc_size%type;
l_blob_data BLOB;

v_blob_len NUMBER;
v_position NUMBER;
v_raw_chunk RAW(10000);
v_char CHAR(1);
c_chunk_len number := 1;
v_line VARCHAR2 (32767) := NULL;
v_data_array wwv_flow_global.vc_arr2;
v_rows number;
v_sr_no number := 1;

begin

select
mime_type, doc_size, blob_content
into
l_mime_type, l_doc_size, l_blob_data
from APEX_APPLICATION_FILES
where id = :P3_ITEM1;

-- Just CSV Format will be process
if l_mime_type = 'text/csv' and l_doc_size > 0 then

v_blob_len := dbms_lob.getlength(l_blob_data);
v_position := 1;

-- Read and convert binary to char
WHILE ( v_position <= v_blob_len ) LOOP
v_raw_chunk := dbms_lob.substr(l_blob_data,c_chunk_len,v_position);
v_char := chr(hex_to_decimal(rawtohex(v_raw_chunk)));
v_line := v_line || v_char;
v_position := v_position + c_chunk_len;
-- When a whole line is retrieved
IF v_char = CHR(10) THEN
v_data_array := f_csv_convert_to_table (v_line);

-- For Debugging purpose!
dbms_output.put_line(
'1#' || v_data_array(1) ||'#' ||
'2#' || v_data_array(2) ||'#' ||
'3#' || v_data_array(3) ||'#' ||
'4#' || v_data_array(4) ||'#' ||
'5#' || v_data_array(5) ||'#' ||
'6#' || v_data_array(6) ||'#' ||
'7#' || v_data_array(7) ||'#' ||
'8#' || v_data_array(8)
);

-- Insert data into target table
EXECUTE IMMEDIATE '
INSERT INTO MSGP_PURCHASEITEM_ALL
( ID, ITEM_NUMBER, ITEM_DESCRIPTION, ITEM_TYPE,
VALUATION_METHOD, U_OF_M_SCHEDULE,
DECIMAL_PLACES_CURRENCY, DECIMAL_PLACES_QTYS,
INVENTORY_ACCOUNT_NUMBER
)
VALUES
( :1,
:2,
:3,
:4,
:5,
:6,
:7,
:8,
:9
)'
USING
v_sr_no,
v_data_array(1),
v_data_array(2),
v_data_array(3),
v_data_array(4),
v_data_array(5),
v_data_array(6),
v_data_array(7),
v_data_array(8);

-- Clear out
v_line := NULL;
v_sr_no := v_sr_no + 1;

END IF;
END LOOP;

-- Seharusnya di Archive bukan didelete
delete APEX_APPLICATION_FILES where id = :P3_ITEM1;
--
end if;

exception
when others then
null;
-- dbms_output.put_line(sqlerrm);
end;

Implementasi utama pada processing CSV tersebut ada pada baris ke-54 s/d baris ke-81,
dimana terlihat bagaimana Array (Collections) ditranspose dan dijadikan argumen dalam DDL INSERT.

Jika memahami bagaimana import Workspace & Application di dalam Oracle APEX silakan download prototype aplikasi ini disini

Mudah-mudahan bisa memberikan pencerahan pada yg mencari solusi yg sama.

Comments

Popular posts from this blog

Configure Reverse Proxy Apache 2 for Oracle APEX 4.0

Just taking note reminder for myself, it's about how to configuring Apache 2 HTTP Server (Not OHS come with Compl CD of Oracle Database) as a front end HTTP Server for APEX 4.0 installed in Oracle XE 10g. Just follow the step as explain below: Install Apache 2.2 Server (Source can be downloaded from http://httpd.apache.org/download.cgi) installed with listening port configure at 8888 Install Oracle XE 10g Database (Download from http://www.oracle.com/technetwork/database/express-edition/downloads/index.html) installed with listening port configure at 7777 Install APEX 4.0 (Download from http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html) After those development tools installed last thing to do is Configure Apache2 to become front server and static images server for APEX 4.0 then do the following steps: Enable/Activate module mod_proxy, proxy_http_module with LoadModule Directive. Configuration example: LoadModule proxy_module /usr/

Intel 3945 Wifi Card Problem Easy Troubleshoot in Ubuntu 10.10

Recently just change my mind to switch back OS to pure Ubuntu (not its derivative). I've been using Mint version of Ubuntu derivative for 2 years. Gradually move with upgrade from Mint 5, Mint 8 to Mint 9 (KDE). Last upgrade (Mint 9 KDE) was to 64 Bit version about 8 months ago. Today just upgrade to 10.10 Ubuntu and find out that I couldn't access office wireless network. After googling, I find out a simple solution from this links So just type this in your terminal: sudo rfkill unblock wifi Type 'dmesg | grep iwl' to see the result that should inform something like this: iwl3945 0000:07:00.0: loaded firmware version 15.32.2.9 And of course available Wifi Network now should appear in Network Manager applet drop down. See picture below for more verbose outcome. After this then I'll applied PAE Kernel to utilized unused 1 GB RAM in my laptop, since 32-bit linux without PAE can only used maximum 3 GB of RAM (mine is 4 GB),... hehehe I'm back to 32-bit world again,