Change external table BADFILE, LOGFILE and DISCARDFILE parameters only

Ollie picture Ollie · Aug 30, 2011 · Viewed 15.7k times · Source

I have several external tables used to read file data into the DB each one for a particular file specification.

For files of a single format a table is reused by pointing it at a new default directory and new file name. This is working fine except I now need to dynamically change the BADFILE, LOGFILE and DISCARDFILE parameters whilst keeping the rest of the access parameters unchanged.

Is there a direct way to do this without having to respecify all the other access parameters (column transformations filed delimiters etc.) as well?

Answer

Ollie picture Ollie · Sep 20, 2011

Unfortunately changing just the BADFILE, LOGFILE and DISCARDFILE parameters couldn't be achieved without having to respecify the other access parameters too.

For what it's worth and for anyone who finds this question in the future i eventually worked around the problem with the following:

Select the external table and use REGEXP_REPLACE on its access parameters to replace the parts of the access parameter BLOB that matched BADFILE, LOGFILE and DISCARDFILE and their associated values with the new values that I supplied.

  CURSOR external_table_cur(
     cp_external_table IN VARCHAR2,
     cp_new_log_dir IN VARCHAR2,
     cp_log_file IN VARCHAR2
  )
  IS
     SELECT table_name,
            REGEXP_REPLACE(
               access_parameters,
               <REGEX PATTERN>,
               cp_new_log_dir||':'''||LOWER(cp_log_file),
               1,
               0,
               'i'
            ) AS new_access_params
       FROM all_external_tables
      WHERE table_name = UPPER(cp_external_table);

I then used dynamic SQL to alter the external table and supplied the new access parameters.

  -- Point external table to new file, directory and access params
  EXECUTE IMMEDIATE(
     'ALTER TABLE '
     || p_table_name
     || ' DEFAULT DIRECTORY '
     || p_directory
     || ' LOCATION ('''
     || p_filename
     || ''') '
     || ' ACCESS PARAMETERS ('
     || TO_CHAR(new_access_params)
     || ')'
  );

It's not ideal and I did end up having to respecify ALL the access parameters but using the REGEX (and fully testing the output) meant the process wasn't too painful or slow.