Before you start
Data Pump runs on the database server, not on the client. Dump files are written to a directory object on the server, and the job runs as background processes (a master process DMnn and workers DWnn). Connect to the PDB service, not the CDB root, unless you really mean to export the root.
-- as a DBA in the PDB
CREATE OR REPLACE DIRECTORY dp_dir AS '/u01/app/oracle/dpdump/sales';
GRANT READ, WRITE ON DIRECTORY dp_dir TO app_admin;
-- full-database or other-schema exports/imports need these roles
GRANT DATAPUMP_EXP_FULL_DATABASE, DATAPUMP_IMP_FULL_DATABASE TO app_admin;
SELECT directory_name, directory_path FROM dba_directories;
The OS folder must exist and be writable by the oracle OS user on the database host. On RAC, use a shared file system, or keep PARALLEL jobs on one instance with CLUSTER=N.
Tip
Don't run Data Pump as
/ as sysdba. Oracle documents that SYSDBA should be used only when Oracle Support asks for it. Use a named DBA account with the Data Pump roles.
Exports (expdp)
Put parameters in a parameter file. You avoid shell quoting problems with QUERY, INCLUDE and EXCLUDE, and you keep a record of what you ran.
Schema export, consistent and parallel
schema_exp.par:
DIRECTORY=dp_dir
DUMPFILE=sales_%U.dmp
LOGFILE=sales_exp.log
SCHEMAS=SALES,SALES_STG
PARALLEL=4
FILESIZE=20G
FLASHBACK_TIME=SYSTIMESTAMP
EXCLUDE=STATISTICS
METRICS=YES
LOGTIME=ALL
expdp app_admin@//dbhost:1521/salespdb PARFILE=schema_exp.par
FLASHBACK_TIME=SYSTIMESTAMPmakes every table consistent to the same point in time. Without it, each table is consistent only to the moment it was exported. That breaks foreign keys in busy schemas.%UwithPARALLELlets each worker write its own file. Use at least as many files as the parallel degree.EXCLUDE=STATISTICSis faster. Gather fresh statistics on the target after the import.
Warning
PARALLELgreater than 1 needs Enterprise Edition.COMPRESSION=ALLandCOMPRESSION=DATA_ONLYneed the Advanced Compression option, andENCRYPTIONneeds Advanced Security unless you are on a cloud service that includes it. Check your licences before using them. The defaultCOMPRESSION=METADATA_ONLYis free.
Other common exports
# a few tables, some rows only
TABLES=SALES.ORDERS,SALES.ORDER_LINES
QUERY=SALES.ORDERS:"WHERE order_date >= DATE '2026-01-01'"
# structure only (DDL, no rows)
CONTENT=METADATA_ONLY
# everything except one big audit table
EXCLUDE=TABLE:"IN ('AUDIT_LOG')"
# full database
FULL=Y
# dump readable by an older target release
VERSION=19
Check the size before exporting:
expdp app_admin@salespdb SCHEMAS=SALES ESTIMATE_ONLY=YES NOLOGFILE=YES
Imports (impdp)
Into a different schema and tablespace
schema_imp.par:
DIRECTORY=dp_dir
DUMPFILE=sales_%U.dmp
LOGFILE=sales_imp.log
SCHEMAS=SALES
REMAP_SCHEMA=SALES:SALES_UAT
REMAP_TABLESPACE=SALES_DATA:UAT_DATA
PARALLEL=4
TABLE_EXISTS_ACTION=SKIP
TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y
METRICS=YES
LOGTIME=ALL
impdp app_admin@//uathost:1521/uatpdb PARFILE=schema_imp.par
TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y cuts redo during the load. It has no effect if the database is in FORCE LOGGING mode (always the case with Data Guard). Take a backup after the import if you use it.
TABLE_EXISTS_ACTION
| Value | What happens to an existing table | Use it when |
|---|---|---|
SKIP (default) | Left alone; import logs ORA-39151 | Re-running a partly failed import |
APPEND | New rows added; existing rows kept | Loading extra data; watch for unique key errors |
TRUNCATE | Rows deleted, then loaded | Refreshing data while keeping grants and indexes |
REPLACE | Table dropped, re-created and loaded | Full refresh of the table definition and data |
Caution
TRUNCATEandREPLACEdestroy the existing data in the target. Double-check the connect string. Importing into production instead of UAT is the classic Data Pump outage.
Useful import variations
# write the DDL to a script instead of running it - review before a real import
SQLFILE=sales_ddl.sql
# only rows, tables already exist
CONTENT=DATA_ONLY
# drop storage clauses so objects use target tablespace defaults
TRANSFORM=SEGMENT_ATTRIBUTES:N
# merge a partitioned table into a non-partitioned one
PARTITION_OPTIONS=MERGE
# rename a table on the way in
REMAP_TABLE=SALES.ORDERS:ORDERS_2026
Without a dump file: NETWORK_LINK
Import straight from a source database over a database link. Nothing is written to disk.
CREATE DATABASE LINK src_sales CONNECT TO app_admin IDENTIFIED BY "********"
USING '//srchost:1521/salespdb';
impdp app_admin@uatpdb NETWORK_LINK=src_sales SCHEMAS=SALES \
REMAP_SCHEMA=SALES:SALES_UAT LOGFILE=dp_dir:net_imp.log
This works well for small and medium schemas. For very large data volumes, export to files with PARALLEL instead. Some data types, such as LONG columns, have restrictions over a network link; check the documentation for your release.
Monitoring and controlling running jobs
-- jobs and their state
SELECT owner_name, job_name, operation, job_mode, state, attached_sessions
FROM dba_datapump_jobs;
-- progress of the current work item
SELECT sid, opname, sofar, totalwork,
ROUND(sofar / NULLIF(totalwork, 0) * 100, 1) AS pct, time_remaining
FROM v$session_longops
WHERE opname LIKE 'SYS_%' AND sofar <> totalwork;
Attach to a running job from any session (job names look like SYS_EXPORT_SCHEMA_01):
expdp app_admin@salespdb ATTACH=SYS_EXPORT_SCHEMA_01
Interactive commands at the Export> or Import> prompt:
| Command | Effect |
|---|---|
STATUS | Progress per worker and bytes written |
PARALLEL=8 | Change the degree while the job runs |
ADD_FILE=extra_%U.dmp | Add dump files (export only) |
STOP_JOB=IMMEDIATE | Pause; restart later with START_JOB |
START_JOB | Resume a stopped job |
KILL_JOB | Abort and delete the master table; the job can't be restarted |
EXIT_CLIENT | Detach; the job keeps running |
Press Ctrl+C in a running client to get the interactive prompt without stopping the job.
Orphaned jobs
A killed client or crashed instance can leave jobs in NOT RUNNING state, with master tables of the same name in the owner's schema.
SELECT owner_name, job_name, state
FROM dba_datapump_jobs
WHERE state = 'NOT RUNNING' AND attached_sessions = 0;
First try ATTACH followed by KILL_JOB. If the job can't be attached and is definitely not a stopped job you want to restart, drop its master table:
DROP TABLE app_admin.sys_export_schema_01 PURGE;
Errors you'll hit
| Error | Usual cause | Fix |
|---|---|---|
| ORA-39002 + ORA-39070 + ORA-29283 | Directory path doesn't exist on the DB server or isn't writable by oracle | Create the OS folder and fix ownership; check dba_directories |
| ORA-39087 directory name is invalid | Directory object missing or no READ/WRITE grant | CREATE DIRECTORY / GRANT READ, WRITE |
| ORA-31684 object already exists | Users, roles or sequences already in the target | Usually harmless; review the log or EXCLUDE those types |
| ORA-39151 table exists | TABLE_EXISTS_ACTION=SKIP | Choose another action if you meant to reload |
| ORA-39083 object type failed to create | Missing grantee, tablespace or dependent object | Read the failing DDL in the log; create the dependency or remap |
| ORA-39142 incompatible version number | Dump made by a newer release than the target | Re-export with VERSION=<target release> |
| ORA-01555 snapshot too old during export | Undo too small for the FLASHBACK_TIME export | Increase undo retention or the undo tablespace; export in a quieter window |
| ORA-31693 table data object failed to load/unload | Row-level error on one table, for example a constraint violation or a full tablespace | Check the next lines in the log; fix and re-import that table |
Prevent it next time
- Keep parameter files in version control and name dump files and logs with the date and source. You'll know exactly what each file contains.
- Always import with
SQLFILEfirst when the target isn't empty, and review the DDL. - Gather statistics after imports with
EXCLUDE=STATISTICS(DBMS_STATS.GATHER_SCHEMA_STATS), and recompile invalid objects withutlrp.sqlorDBMS_UTILITY.COMPILE_SCHEMA. - Data Pump is a logical copy, not a backup strategy. Use RMAN for recovery.