DBMS_DATAPUMP имеет несколько действительно хороших сообщений об ошибках, но вам нужно покопаться, чтобы их получить. В приведенном ниже примере я добавил вложенную процедуру output_expdp_error для вывода подробного сообщения. Конечно, вы должны изменить это, чтобы сделать соответствующую регистрацию для вашей среды:
DECLARE
h1 NUMBER;
l_filename VARCHAR2( 100 ) := 'deleteme.dmp';
l_directory VARCHAR2( 100 ) := 'CIFS_DIR';
PROCEDURE output_expdpd_error( p_handle IN NUMBER ) AS
-- *******************************************************************
-- Output EXPDP Error
-- Purpose:
-- Send detailed EXPDP error to DBMS_OUTPUT
-- Modified:
-- 2020.03.02 - BFL Created
-- Notes:
-- Borrowed from: https://docs.oracle.com/database/121/SUTIL/GUID-5AAC848B-5A2B-4FD1-97ED-D3A048263118.htm#SUTIL977
-- *******************************************************************
l_status ku$_status; --ku$_jobstatus;
l_logentry ku$_logentry;
l_job_state VARCHAR2( 30 );
l_ind NUMBER;
l_pos NUMBER;
l_length NUMBER;
l_linesize CONSTANT NUMBER := 1000;
l_message VARCHAR2( 1000 );
BEGIN
-- Original had "if sqlcode = dbms_datapump.success_with_info_num" but this
-- hides some errors. Just always process the handle.
DBMS_OUTPUT.put_line( 'Data Pump job started with info available:' );
DBMS_DATAPUMP.get_status( p_handle
, DBMS_DATAPUMP.ku$_status_job_error
, 0
, l_job_state
, l_status );
IF (BITAND( l_status.mask, DBMS_DATAPUMP.ku$_status_job_error ) != 0)
THEN
l_logentry := l_status.error;
IF l_logentry IS NOT NULL
THEN
l_ind := l_logentry.FIRST;
WHILE l_ind IS NOT NULL
LOOP
l_pos := 1;
l_length := LENGTH( l_logentry( l_ind ).logtext );
l_length := CASE WHEN l_linesize < l_length THEN l_linesize ELSE l_length END;
WHILE l_length > 0
LOOP
l_message :=
SUBSTR( l_logentry( l_ind ).logtext
, l_pos
, l_length );
DBMS_OUTPUT.put_line( l_message );
l_pos := l_pos + l_linesize;
l_length := LENGTH( l_logentry( l_ind ).logtext ) + 1 - l_pos;
END LOOP;
l_ind := l_logentry.NEXT( l_ind );
END LOOP;
END IF;
END IF;
END;
BEGIN
DBMS_OUTPUT.put_line( 'open' );
h1 := DBMS_DATAPUMP.open( 'EXPORT', 'SCHEMA' );
DBMS_OUTPUT.put_line( 'add_file' );
DBMS_DATAPUMP.add_file( handle => h1
, filename => l_filename
, directory => l_directory
, filetype => DBMS_DATAPUMP.ku$_file_type_dump_file
, reusefile => 1 );
DBMS_OUTPUT.put_line( 'hr filter' );
DBMS_DATAPUMP.metadata_filter( h1
, 'SCHEMA_EXPR'
, 'IN (''BOGUS'')' );
DBMS_OUTPUT.put_line( 'BOGUS filter' );
DBMS_DATAPUMP.metadata_filter( h1
, 'SCHEMA_EXPR'
, 'IN (''BOGUS'')' );
DBMS_OUTPUT.put_line( 'start_job' );
DBMS_DATAPUMP.start_job( h1 );
DBMS_DATAPUMP.detach( h1 );
EXCEPTION
WHEN OTHERS
THEN
DECLARE
l_message VARCHAR2( 1000 );
BEGIN
output_expdpd_error( p_handle => h1 );
DBMS_DATAPUMP.detach( h1 );
l_message :=
SUBSTR(
SQLERRM
|| UTL_TCP.crlf
|| DBMS_UTILITY.format_error_backtrace
|| UTL_TCP.crlf
|| UTL_TCP.crlf
, 1
, 1000 );
DBMS_OUTPUT.put_line( l_message );
raise_application_error( -20000, l_message );
END;
END;
Когда я запустил это с несуществующей схемой, я получил чудесно указанное c сообщение об ошибке:
ORA-39001: invalid argument value
ORA-39170: Schema expression IN ('BOGUS') does not correspond to any schemas.
ORA-39001: invalid argument value
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 79
ORA-06512: at "SYS.DBMS_DATAPUMP", line 3507
ORA-06512: at "SYS.DBMS_DATAPUMP", line 4825
ORA-06512: at line 76