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.