In order to keep the process fluid, we eliminated the need to load an actual 'table' by using pipe lined funtions. Essentialy, my function will take in a .csv style formatted clob, and 'pipe' rows back. Note: You do have to create user defined types in order make this work, as the table is returning a 'row' of that type. You can read more about pipe lined functionality here .
FUNCTION EMAIL_PARSE RETURN GOOGLE_APPS_EMAIL_TABLE
PIPELINED IS
/***
** Function: GOOGLE_EMAIL_PARSE
** Params: none
** Returns: Table of GOOGLE_APPS_EMAIL_ROW type
** Description: Pipelined function fetchs the .csv type clob from Google Reporting API and parses
** it out into a table using regular expressions.
***/
ROW_STRING VARCHAR2(4000);
V_MESSAGE VARCHAR2(4000);
--Our current place in the clob
CLOB_LOCATION NUMBER := 1;
--The clob we want to parse
PARSE_CLOB CLOB := /* your clob here*/;
BEGIN
--Loop to parse out fields for every single row.
FOR I IN 1 .. REGEXP_COUNT(PARSE_CLOB, '^.*?', MODIFIER => 'm') - 1 --because we eliminate header row, need to decrement count
LOOP
--Get next 'row' of data
ROW_STRING := REGEXP_SUBSTR(PARSE_CLOB, '.*$?', CLOB_LOCATION);
--Increment our location appropriately
CLOB_LOCATION := CLOB_LOCATION + LENGTH(ROW_STRING) + 1;
--Replacing any , inside fields with - so our regexp can recognize it as a field.
ROW_STRING := REGEXP_REPLACE(ROW_STRING, '(")(.*?)(,)(.*?)(")', '\2-\4');
ROW_STRING := REPLACE(ROW_STRING, ',', ' ,');
--Returning our rows.
PIPE ROW(D/*your row type */(TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 1))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 2))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 3))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 4))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 5))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 6)) /*usage in bytes*/
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 7))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 8))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 9))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 10))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 11)) /*last_web_mail_date */
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 12))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 13))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 14))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 15))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 16))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 17))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 18))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 19))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 20))
,TRIM(REGEXP_SUBSTR(ROW_STRING, '[^,]+', OCCURRENCE => 21))));
-- END IF;
END LOOP;
RETURN;
EXCEPTION
--when we don't need more data, do nothing.
WHEN NO_DATA_NEEDED THEN
NULL;
WHEN OTHERS THEN
V_MESSAGE := 'There was an error in parsing the clob EMAIL_PARSE: ' || SQLERRM;
--Email admins here
END;