Ich hatte häufiger das Problem, dass ich in unserer Produktionsumgebung einen Schema-Dump ziehen wollte, mich aber nicht auf dem Datenbank-Server anmelden konnte, weil gerade getestet wurde. Da die Operator im allgemeinen nicht gerade erfreut waren, wenn plötzlich neue Kommandozeilenfenster auf ihrem Display auftauchten, bastelte ich mir einfach eine Prozedur für den Datapump-Import übers Netzwerk. Diese Möglichkeit gibt es schon seit "ewigen" Zeiten (seit Version 10g).
Der Import benötigt zwar durchaus Ressourcen, aber die Tests wurden dadurch nicht spürbar langsamer und ersparten mir und den Kollegen in Asien Downtimes für Wartungsfenster.
Der Code:
CREATE OR REPLACE PROCEDURE prc_schema_import_net (
schema_in VARCHAR2 DEFAULT user, -- Schemaname
schema_new_in VARCHAR2 DEFAULT NULL, -- Zielschema
parallel_in VARCHAR2 DEFAULT 1,
directory_in VARCHAR2 DEFAULT 'DATA_PUMP_DIR', -- für das Logfile
db_link_in VARCHAR2)
IS
l_job_name VARCHAR2(100);
l_idx NUMBER;
l_handle NUMBER;
l_percent_done NUMBER := 0;
l_job_state VARCHAR2(30) := 'n.a.';
-- nested Tables für das Monitoring des Import-Jobs
logentry_nt KU$_LOGENTRY;
jobstatus_nt KU$_JOBSTATUS;
jobdesc_nt KU$_JOBDESC;
status_nt KU$_STATUS;
BEGIN
l_job_name := RTRIM(TO_CHAR(sysdate,
'yyyymmdd-hh24mi')||'_imp_'||schema_in||'_'||schema_new_in, '_');
-- einen neuen Datapump-Job erstellen
l_handle := DBMS_DATAPUMP.OPEN (
operation => 'IMPORT',
job_mode => 'SCHEMA',
job_name => l_job_name,
remote_link => db_link_in);
-- Optionale Parallelisierung
IF NVL(parallel_in,1) > 1 THEN
DBMS_DATAPUMP.SET_PARALLEL(l_handle, parallel_in);
END IF;
-- Abschnitt für das Logfile (dafür braucht's ein Directory
-- auch wenn der Dump selbst nicht gespeichert werden muss)
DBMS_DATAPUMP.ADD_FILE (
handle => l_handle,
filename => l_job_name||'.log',
directory => UPPER(directory_in),
filetype => DBMS_DATAPUMP.ku$_file_type_log_file);
-- Export aller Objekte des Schemas zum selben Zeitpunkt
DBMS_DATAPUMP.SET_PARAMETER (
handle => l_handle,
name => 'FLASHBACK_TIME',
value => 'systimestamp');
-- Schemanamen übergeben
DBMS_DATAPUMP.METADATA_FILTER (
handle => l_handle,
name => 'SCHEMA_EXPR',
value => '='''||UPPER(schema_in)||'''');
-- Beispiel für Objekte, die weggelassen werden sollen
DBMS_DATAPUMP.METADATA_FILTER (
handle => l_handle,
name => 'EXCLUDE_PATH_EXPR',
value => 'IN (''GRANT'',''STATISTICS'',''DB_LINK'')');
-- falls gewünscht, Schemanamen beim Import ändern
-- das Zielschema muss bereits existieren
IF schema_new_in IS NOT NULL THEN
DBMS_DATAPUMP.METADATA_REMAP (
handle => l_handle,
name => 'REMAP_SCHEMA',
old_value => UPPER(schema_in),
value => UPPER(schema_new_in));
END IF;
-- Job starten
DBMS_DATAPUMP.START_JOB (handle => l_handle);
-- Monitoring
WHILE l_job_state NOT IN ('COMPLETED', 'STOPPED') LOOP
DBMS_DATAPUMP.GET_STATUS(
handle => l_handle,
mask => DBMS_DATAPUMP.ku$_status_job_error +
DBMS_DATAPUMP.ku$_status_job_status +
DBMS_DATAPUMP.ku$_status_wip,
timeout => -1,
job_state => l_job_state,
status => status_nt);
jobStatus_nt := status_nt.job_status;
-- Der Fortschritt wird über percent_done angezeigt
IF jobstatus_nt.percent_done != l_percent_done THEN
DBMS_OUTPUT.PUT_LINE('Abgeschlossen %: ' ||
jobstatus_nt.percent_done);
l_percent_done := jobstatus_nt.percent_done;
END IF;
-- Sammlung von work-in-progress und Fehlermeldungen für den Job
IF BITAND(status_nt.mask, DBMS_DATAPUMP.ku$_status_wip) != 0 THEN
logentry_nt := status_nt.wip;
ELSE
IF BITAND(status_nt.mask,
DBMS_DATAPUMP.ku$_status_job_error) != 0 THEN
logentry_nt := status_nt.error;
ELSE
logentry_nt := null;
END IF;
END IF;
-- wenn Fehlermeldungen aufgetaucht sind, durch die nested Table
-- navigieren und die Fehler anzeigen
IF logentry_nt IS NOT NULL THEN
l_idx := logentry_nt.FIRST;
WHILE l_idx IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE(logentry_nt(l_idx).LogText);
l_idx := logentry_nt.NEXT(l_idx);
END LOOP;
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Job abgeschlossen, Status: ' || l_job_state);
DBMS_DATAPUMP.DETACH (handle => l_handle);
EXCEPTION
WHEN OTHERS THEN
-- Wenn die Schritt OPEN und ATTACH nicht geklappt haben,
-- dann ist der Jobhandle NULL
DBMS_DATAPUMP.GET_STATUS(
handle => NULL,
mask => 8,
timeout => 0,
job_state => l_job_state,
status => status_nt);
logentry_nt := status_nt.error;
l_idx := logentry_nt.FIRST;
LOOP
EXIT WHEN l_idx IS NULL;
DBMS_OUTPUT.PUT_LINE('logLineNumber: ' ||
logentry_nt(l_idx).logLineNumber);
DBMS_OUTPUT.PUT_LINE('errorNumber: ' || logentry_nt(l_idx).errorNumber);
DBMS_OUTPUT.PUT_LINE('LogText: ' || logentry_nt(l_idx).LogText);
l_idx := logentry_nt.NEXT(l_idx);
END LOOP;
DBMS_DATAPUMP.STOP_JOB(l_handle);
RAISE;
END prc_schema_import_net;
Beispiel:
Als User system auf der Zieldatenbank
set serveroutput on
BEGIN
prc_schema_import_net (
schema_in => 'prod',
directory_in => 'extern',
db_link_in => 'prod_remote');
END;
Ausgabe z.B.
Master-Tabelle "SYSTEM"."20260420-2124_imp_prod" erfolgreich geladen/entladen
"SYSTEM"."20260420-2124_imp_prod": wird gestartet
Objekttyp SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA wird verarbeitet
Objekttyp SCHEMA_EXPORT/DB_LINK wird verarbeitet
Objekttyp SCHEMA_EXPORT/SEQUENCE/SEQUENCE wird verarbeitet
Objekttyp SCHEMA_EXPORT/TABLE/TABLE wird verarbeitet
Objekttyp SCHEMA_EXPORT/TABLE/TABLE_DATA wird verarbeitet
Abgeschlossen %: 48
. . "PROD"."RESULTS" 270.1 MB 5350208 Zeilen importiert
Abgeschlossen %: 90
. . "PROD"."TRACE_LOG" 40.86 MB 102257 Zeilen importiert
Abgeschlossen %: 96
. . "PROD"."DEVICETEST" 12.47 MB 206042 Zeilen importiert
Abgeschlossen %: 97
. . "PROD"."DEVICES" 6.472 MB 106365 Zeilen importiert
Abgeschlossen %: 98
....
Objekttyp SCHEMA_EXPORT/PACKAGE/PACKAGE_SPEC wird verarbeitet
Objekttyp SCHEMA_EXPORT/PROCEDURE/PROCEDURE wird verarbeitet
Objekttyp SCHEMA_EXPORT/PACKAGE/COMPILE_PACKAGE/PACKAGE_SPEC/ALTER_PACKAGE_SPEC wird verarbeitet
Objekttyp SCHEMA_EXPORT/PROCEDURE/ALTER_PROCEDURE wird verarbeitet
Objekttyp SCHEMA_EXPORT/TABLE/INDEX/INDEX wird verarbeitet
Objekttyp SCHEMA_EXPORT/TABLE/INDEX/FUNCTIONAL_INDEX/INDEX wird verarbeitet
Objekttyp SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT wird verarbeitet
Objekttyp SCHEMA_EXPORT/VIEW/VIEW wird verarbeitet
Objekttyp SCHEMA_EXPORT/PACKAGE/PACKAGE_BODY wird verarbeitet
Objekttyp SCHEMA_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT wird verarbeitet
Job "SYSTEM"."20260420-2124_imp_prod " um Mo Apr 20 21:28:10 2026 elapsed 0 00:01:23 abgeschlossen
Job abgeschlossen, Status: COMPLETED
Ein paar Tips zum Troubleshooting und eine weitere Einsatzmöglichkeit für die Prozedur folgen in der Fortsetzung dieser Kolumne.
Elke Fritsch

