I've searched many forums on here about uploading .cvs files into tables and have ran across the example from Vikas about the file upload (with creating a table) and i've also ran across another example (I believe by JMcG) uploads the data into an existing table.
Both examples have worked correctly for me, however, they do not do what I would like them to do.
Basically, my user will download a spreadsheet from a tabular form with empty cells where there is no data. They will then put data into the empty cells and I am wondering how to edit the two examples above (code/link provided below for the JMcG upload to existing table) so that when my user uploads the file it updates the correct information in my table instaed of just making a new row.
code that I need to execute:
UPDATE table_name
SET table_col2 = csv_col2, table_col3 = csv_col3, ......... table_colN = csv_colN
where table_PK = csv_col1
create or replace PACKAGE BODY htmldb_tools
AS
TYPE varchar2_t IS TABLE OF VARCHAR2(32767) INDEX BY binary_integer;
-- Private functions --{{{
PROCEDURE delete_collection ( --{{{
-- Delete the collection if it exists
p_collection_name IN VARCHAR2
)
IS
BEGIN
IF (htmldb_collection.collection_exists(p_collection_name))
THEN
htmldb_collection.delete_collection(p_collection_name);
END IF;
END delete_collection; --}}}
PROCEDURE csv_to_array ( --{{{
-- Utility to take a CSV string, parse it into a PL/SQL table
-- Note that it takes care of some elements optionally enclosed
-- by double-quotes.
p_csv_string IN VARCHAR2,
p_array OUT wwv_flow_global.vc_arr2,
p_separator IN VARCHAR2 := ','
)
IS
l_start_separator PLS_INTEGER := 0;
l_stop_separator PLS_INTEGER := 0;
l_length PLS_INTEGER := 0;
l_idx BINARY_INTEGER := 0;
l_quote_enclosed BOOLEAN := FALSE;
l_offset PLS_INTEGER := 1;
BEGIN
l_length := NVL(LENGTH(p_csv_string),0);
IF (l_length <= 0)
THEN
RETURN;
END IF;
LOOP
l_idx := l_idx + 1;
l_quote_enclosed := FALSE;
IF SUBSTR(p_csv_string, l_start_separator + 1, 1) = '"'
THEN
l_quote_enclosed := TRUE;
l_offset := 2;
l_stop_separator := INSTR(p_csv_string, '"', l_start_separator + l_offset, 1);
ELSE
l_offset := 1;
l_stop_separator := INSTR(p_csv_string, p_separator, l_start_separator + l_offset, 1);
END IF;
IF l_stop_separator = 0
THEN
l_stop_separator := l_length + 1;
END IF;
p_array(l_idx) := (SUBSTR(p_csv_string, l_start_separator + l_offset,(l_stop_separator - l_start_separator - l_offset)));
EXIT WHEN l_stop_separator >= l_length;
IF l_quote_enclosed
THEN
l_stop_separator := l_stop_separator + 1;
END IF;
l_start_separator := l_stop_separator;
END LOOP;
END csv_to_array; --}}}
PROCEDURE get_records(p_blob IN blob,p_records OUT varchar2_t) --{{{
IS
l_record_separator VARCHAR2(2) := chr(13)||chr(10);
l_last INTEGER;
l_current INTEGER;
BEGIN
-- Sigh, stupid DOS/Unix newline stuff. If HTMLDB has generated the file,
-- it will be a Unix text file. If user has manually created the file, it
-- will have DOS newlines.
-- If the file has a DOS newline (cr+lf), use that
-- If the file does not have a DOS newline, use a Unix newline (lf)
IF (NVL(dbms_lob.instr(p_blob,utl_raw.cast_to_raw(l_record_separator),1,1),0)=0)
THEN
l_record_separator := chr(10);
END IF;
l_last := 1;
LOOP
l_current := dbms_lob.instr( p_blob, utl_raw.cast_to_raw(l_record_separator), l_last, 1 );
EXIT WHEN (nvl(l_current,0) = 0);
p_records(p_records.count+1) := utl_raw.cast_to_varchar2(dbms_lob.substr(p_blob,l_current-l_last,l_last));
l_last := l_current+length(l_record_separator);
END LOOP;
END get_records; --}}}
--}}}
-- Utility functions --{{{
PROCEDURE parse_textarea ( --{{{
p_textarea IN VARCHAR2,
p_collection_name IN VARCHAR2
)
IS
l_index INTEGER;
l_string VARCHAR2(32767) := TRANSLATE(p_textarea,chr(10)||chr(13)||' ,','@@@@');
l_element VARCHAR2(100);
BEGIN
l_string := l_string||'@';
htmldb_collection.create_or_truncate_collection(p_collection_name);
LOOP
l_index := instr(l_string,'@');
EXIT WHEN NVL(l_index,0)=0;
l_element := substr(l_string,1,l_index-1);
IF (trim(l_element) IS NOT NULL)
THEN
htmldb_collection.add_member(p_collection_name,l_element);
END IF;
l_string := substr(l_string,l_index+1);
END LOOP;
END parse_textarea; --}}}
PROCEDURE parse_file( --{{{
p_file_name IN VARCHAR2,
p_collection_name IN VARCHAR2,
p_headings_item IN VARCHAR2,
p_columns_item IN VARCHAR2,
p_ddl_item IN VARCHAR2,
p_table_name IN VARCHAR2 DEFAULT NULL
)
IS
l_blob blob;
l_records varchar2_t;
l_record wwv_flow_global.vc_arr2;
l_datatypes wwv_flow_global.vc_arr2;
l_headings VARCHAR2(4000);
l_columns VARCHAR2(4000);
l_seq_id NUMBER;
l_num_columns INTEGER;
l_ddl VARCHAR2(4000);
BEGIN
IF (p_table_name is not null)
THEN
/*
BEGIN
execute immediate 'drop table '||p_table_name;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
l_ddl := 'create table '||p_table_name||' '||v(p_ddl_item);
htmldb_util.set_session_state('P149_DEBUG',l_ddl);
execute immediate l_ddl;
*/
--My PL/SQL APEX knowledge is not that great right now, but I believe in order to accomplish this task, the below "insert into" statement is what
needs to be changed.
l_ddl := 'insert into '||p_table_name||' '||
'select '||v(p_columns_item)||' '||
'from htmldb_collections '||
'where seq_id > 0 and collection_name='''||p_collection_name||'''';
htmldb_util.set_session_state('P149_DEBUG',v('P149_DEBUG')||'/'||l_ddl);
execute immediate l_ddl;
RETURN;
END IF;
BEGIN
select blob_content into l_blob from wwv_flow_files
where name=p_file_name;
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise_application_error(-20000,'File not found, id='||p_file_name);
END;
get_records(l_blob,l_records);
IF (l_records.count < 2)
THEN
raise_application_error(-20000,'File must have at least 3 ROWS, id='||p_file_name);
END IF;
-- Initialize collection
htmldb_collection.create_or_truncate_collection(p_collection_name);
-- Get column headings and datatypes
csv_to_array(l_records(1),l_record);
csv_to_array(l_records(2),l_datatypes);
l_num_columns := l_record.count;
if (l_num_columns > 50) then
raise_application_error(-20000,'Max. of 50 columns allowed, id='||p_file_name);
end if;
-- Get column headings and names
FOR i IN 1..l_record.count
LOOP
l_headings := l_headings||':'||l_record(i);
l_columns := l_columns||',c'||lpad(i,3,'0');
END LOOP;
l_headings := ltrim(l_headings,':');
l_columns := ltrim(l_columns,',');
htmldb_util.set_session_state(p_headings_item,l_headings);
htmldb_util.set_session_state(p_columns_item,l_columns);
/*
-- Get datatypes
FOR i IN 1..l_record.count
LOOP
l_ddl := l_ddl||','||l_record(i)||' '||l_datatypes(i);
END LOOP;
l_ddl := '('||ltrim(l_ddl,',')||')';
htmldb_util.set_session_state(p_ddl_item,l_ddl);
*/
-- Save data into specified collection
FOR i IN 2..l_records.count
LOOP
csv_to_array(l_records(i),l_record);
l_seq_id := htmldb_collection.add_member(p_collection_name,'dummy');
FOR i IN 1..l_record.count
LOOP
htmldb_collection.update_member_attribute(
p_collection_name=> p_collection_name,
p_seq => l_seq_id,
p_attr_number => i,
p_attr_value => l_record(i)
);
END LOOP;
END LOOP;
DELETE FROM wwv_flow_files WHERE name=p_file_name;
END;
BEGIN
NULL;
END;
Any and all help is appreciated!
Thanks
Doolius