Using the DBMS_METADATA API to Re-Create a Retrieved Object

When you fetch metadata for an object, you may want to use it to re-create the object in a different database or schema.

You may not be ready to make remapping decisions when you fetch the metadata. You may want to defer these decisions until later. To accomplish this, you fetch the metadata as XML and store it in a file or table. Later you can use the submit interface to re-create the object.

The submit interface is similar in form to the retrieval interface. It has an OPENW procedure in which you specify the object type of the object to be created. You can specify transforms, transform parameters, and parse items. You can call the CONVERT function to convert the XML to DDL, or you can call the PUT function to both convert XML to DDL and submit the DDL to create the object.

See Also:

Table 21-3 for descriptions of DBMS_METADATA procedures and functions used in the submit interface

Example 21-7 fetches the XML for a table in one schema, and then uses the submit interface to re-create the table in another schema.

Example 21-7 Using the Submit Interface to Re-Create a Retrieved Object

  1. Connect as a privileged user:

    CONNECT system
    Enter password: password
    
  2. Create an invoker's rights package to hold the procedure because access to objects in another schema requires the SELECT_CATALOG_ROLE role. In a definer's rights PL/SQL object (such as a procedure or function), roles are disabled.

    CREATE OR REPLACE PACKAGE example_pkg AUTHID current_user IS
      PROCEDURE move_table(
            table_name  in VARCHAR2,
            from_schema in VARCHAR2,
            to_schema   in VARCHAR2 );
    END example_pkg;
    /
    CREATE OR REPLACE PACKAGE BODY example_pkg IS
    PROCEDURE move_table(
            table_name  in VARCHAR2,
            from_schema in VARCHAR2,
            to_schema   in VARCHAR2 ) IS
    
    -- Define local variables.
    h1      NUMBER;         -- handle returned by OPEN
    h2      NUMBER;         -- handle returned by OPENW
    th1     NUMBER;         -- handle returned by ADD_TRANSFORM for MODIFY
    th2     NUMBER;         -- handle returned by ADD_TRANSFORM for DDL
    xml     CLOB;           -- XML document
    errs    sys.ku$_SubmitResults := sys.ku$_SubmitResults();
    err     sys.ku$_SubmitResult;
    result  BOOLEAN;
    BEGIN
    
    -- Specify the object type.
    h1 := DBMS_METADATA.OPEN('TABLE');
    
    -- Use filters to specify the name and schema of the table.
    DBMS_METADATA.SET_FILTER(h1,'NAME',table_name);
    DBMS_METADATA.SET_FILTER(h1,'SCHEMA',from_schema);
    
    -- Fetch the XML.
    xml := DBMS_METADATA.FETCH_CLOB(h1);
    IF xml IS NULL THEN
        DBMS_OUTPUT.PUT_LINE('Table ' || from_schema || '.' || table_name
    || ' not found');
        RETURN;
      END IF;
    
    -- Release resources.
    DBMS_METADATA.CLOSE(h1);
    
    -- Use the submit interface to re-create the object in another schema.
    
    -- Specify the object type using OPENW (instead of OPEN).
    h2 := DBMS_METADATA.OPENW('TABLE');
    
    -- First, add the MODIFY transform.
    th1 := DBMS_METADATA.ADD_TRANSFORM(h2,'MODIFY');
    
    -- Specify the desired modification: remap the schema name.
    DBMS_METADATA.SET_REMAP_PARAM(th1,'REMAP_SCHEMA',from_schema,to_schema);
    
    -- Now add the DDL transform so that the modified XML can be
    --  transformed into creation DDL.
    th2 := DBMS_METADATA.ADD_TRANSFORM(h2,'DDL');
    
    -- Call PUT to re-create the object.
    result := DBMS_METADATA.PUT(h2,xml,0,errs);
    
    DBMS_METADATA.CLOSE(h2);
      IF NOT result THEN
        -- Process the error information.
        FOR i IN errs.FIRST..errs.LAST LOOP
          err := errs(i);
          FOR j IN err.errorLines.FIRST..err.errorLines.LAST LOOP
            dbms_output.put_line(err.errorLines(j).errorText);
          END LOOP;
        END LOOP;
      END IF;
    END;
    END example_pkg;
    /
    
  3. Now create a table named my_example in the schema SCOTT:

    CONNECT scott
    Enter password:
    -- The password is tiger.
    
    DROP TABLE my_example;
    CREATE TABLE my_example (a NUMBER, b VARCHAR2(30));
    
    CONNECT system
    Enter password: password
    
    SET LONG 9000000
    SET PAGESIZE 0
    SET SERVEROUTPUT ON SIZE 100000
    
  4. Copy the my_example table to the SYSTEM schema:

    DROP TABLE my_example;
    EXECUTE example_pkg.move_table('MY_EXAMPLE','SCOTT','SYSTEM');
    
  5. Perform the following query to verify that it worked:

    SELECT DBMS_METADATA.GET_DDL('TABLE','MY_EXAMPLE') FROM dual;