Oracle
professionals must frequently "punch," or extract, table and
index definitions from Oracle and move them to different
systems. Extracting Data Definition Language (DDL) for Oracle
schema objects (e.g., tables, indexes, stored procedures,
triggers, sequences, etc.) from the dictionary is very useful
when you're migrating a system to a new platform and you want
to pre-create the objects in a new tablespace.
Generally, in an Oracle migration, the schema and DDL are
created in the target database, and then the rows are imported
into the new database using the Oracle imp utility with
the IGNORE=Y parameter. The IGNORE=Y parameters
tells Oracle to use the new DDL definitions instead of the DDL
inside the import data file.
Prior to Oracle9i, getting table and index DDL was a
time-consuming and tricky process. You could run the export
utility (exp) with ROWS=NO, but the output was
hard to reuse because of quoted strings on each line and poor
formatting. The only other option was to write complex
dictionary scripts that might not work on complex objects such
as IOT and nested tables.
After Oracle9i, you can use the dbms_metadata
utility package will easily display DDL and
stored procedures directly from the data dictionary. Using
this powerful utility, you can punch individual objects or an
entire Oracle schema. Best of all, it is easy to use. You
simply execute dbms_metadata.get_ddl, specify the
object names, and Oracle will extract ready-to-use DDL.
To punch off all table and indexes for the EMP table, execute
dbms_metadata. get_ddl, select from DUAL, and provide
all required parameters as shown in Listing A:
Listing A:
set heading off;
set echo off;
Set pages 999;
set long 90000;
spool ddl_list.sql
select dbms_metadata.get_ddl('TABLE','DEPT','SCOTT') from dual;
select dbms_metadata.get_ddl('INDEX','DEPT_IDX','SCOTT') from dual;
spool off;
The output is shown below.

The only thing missing is the ending
semicolons after each statement. Just for illustration, I'm
showing how a primary key can be punched as part of the table
DDL or separately using the INDEX argument.
Note that you have complete table and index definitions,
including storage parameters (e.g., pctfree, pctused,
freelists, and freelist groups) as well as
tablespace storage and buffer pool directives.
For large migrations, you can modify the dbms_metadata
syntax to punch a whole schema. As you can see in
Listing C, it is easily done by selecting
dbms_metadata. get_ddl and specifying USER_TABLES and
USER_INDEXES. This syntax will punch all table and index
definitions for the entire schema, in this example, the
scott schema.
Listing C:
set pagesize 0
set long 90000
set feedback off
set echo off
spool scott_schema.sql
connect scott/tiger;
SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name)
FROM USER_TABLES u;
SELECT DBMS_METADATA.GET_DDL('INDEX',u.index_name)
FROM USER_INDEXES u;
spool off;
Punching PL/SQL from Oracle
The dbms_metadata utility is also used for punching
source code, PL/SQL, and Java that is stored inside Oracle
packages. Stored procedures or functions can also easily be
extracted using dbms_metadata.
In the example in
Listing D, I extract all procedures associated with
the fred schema.
Listing D:
connect fred/flintstone;
spool procedures_punch.lst
select
DBMS_METADATA.GET_DDL('PROCEDURE',u.object_name)
from
user_objects u
where
object_type = 'PROCEDURE';
spool off;
The dbms_metadata utility is especially good for
extracting procedural code because all of the original
formatting is retained.
Listing E is an example of the output from
dbms_metadata for stored procedures.

Issues with dbms_metadata
Like all new Oracle utilities, there are some shortcomings
with dbms_metadata. When you have tables with foreign
key referential integrity (e.g., Oracle’s references
constraints), it would be nice to have dbms_metadata
punch the table DDL in its proper order for reloading into
another database. If you don't punch the tables in the proper
order of foreign key referential integrity, a table may be
added that references another table that has not yet been
added. Making this change would involve adding a WHERE clause
that queries dba_constraints and dba_cons_columns
to determine the proper table order.
Despite the immediate shortcomings, the dbms_metadata
utility is fantastic for extracting DDL and procedural code
from Oracle. I have no doubt a future release of Oracle will
make dbms_metadata even more powerful.
For additional information