【Oracle】DBMS_METADATA完全ガイド|GET_DDL でテーブル・インデックス・ビュー・プロシージャの DDL を取得する方法まで解説

テーブルやインデックス・ビュー・ストアドプロシージャの CREATE 文(DDL)を取得したい場面は多くあります。再現環境の構築・別スキーマへのオブジェクト移行・ドキュメント作成など様々な用途です。

DBMS_METADATA パッケージを使うと、SQL Developer の「DDL を表示」と同等の処理を SQL または PL/SQL から実行できます。スクリプト化・自動化・バッチ処理との組み合わせが可能です。

この記事でわかること

  • DBMS_METADATA.GET_DDL でオブジェクトの DDL を取得する方法
  • テーブル・インデックス・ビュー・シーケンス・プロシージャ・パッケージの DDL 取得
  • GET_DEPENDENT_DDL でトリガー・権限・インデックスなどの依存オブジェクトを取得する
  • SET_TRANSFORM_PARAM でセミコロン付加・表領域情報の制御などを行う
  • OPEN/FETCH/CLOSE スタイルでスキーマ内の複数オブジェクトを一括取得する
スポンサーリンク

DBMS_METADATA.GET_DDL の基本的な使い方

テーブルの DDL を取得する
-- 基本構文: DBMS_METADATA.GET_DDL(object_type, object_name, schema)
-- schema を省略すると現在のスキーマが対象になる

-- テーブルの DDL を取得
SELECT DBMS_METADATA.GET_DDL('TABLE', 'EMPLOYEES') FROM DUAL;

-- 他のスキーマのテーブルを指定する(権限が必要)
SELECT DBMS_METADATA.GET_DDL('TABLE', 'EMPLOYEES', 'HR') FROM DUAL;

-- SQL*Plus / SQLcl で見やすく表示する場合
SET LONG 100000
SET LINESIZE 200
SET PAGESIZE 0
SELECT DBMS_METADATA.GET_DDL('TABLE', 'EMPLOYEES') AS DDL FROM DUAL;
様々なオブジェクト種類の DDL を取得する
-- インデックス
SELECT DBMS_METADATA.GET_DDL('INDEX', 'EMP_NAME_IX') FROM DUAL;

-- ビュー
SELECT DBMS_METADATA.GET_DDL('VIEW', 'EMP_VIEW') FROM DUAL;

-- シーケンス
SELECT DBMS_METADATA.GET_DDL('SEQUENCE', 'EMP_SEQ') FROM DUAL;

-- ストアドプロシージャ(本体のみ)
SELECT DBMS_METADATA.GET_DDL('PROCEDURE', 'MY_PROC') FROM DUAL;

-- ファンクション
SELECT DBMS_METADATA.GET_DDL('FUNCTION', 'MY_FUNC') FROM DUAL;

-- パッケージ仕様部
SELECT DBMS_METADATA.GET_DDL('PACKAGE', 'MY_PKG') FROM DUAL;

-- パッケージ本体
SELECT DBMS_METADATA.GET_DDL('PACKAGE_BODY', 'MY_PKG') FROM DUAL;

-- トリガー
SELECT DBMS_METADATA.GET_DDL('TRIGGER', 'MY_TRIGGER') FROM DUAL;

-- 型(TYPE)
SELECT DBMS_METADATA.GET_DDL('TYPE', 'MY_TYPE') FROM DUAL;

-- データベースリンク
SELECT DBMS_METADATA.GET_DDL('DB_LINK', 'MY_DBLINK') FROM DUAL;

-- 表領域(DBA権限が必要)
SELECT DBMS_METADATA.GET_DDL('TABLESPACE', 'USERS') FROM DUAL;

SET_TRANSFORM_PARAM で DDL の出力形式を制御する

デフォルトの GET_DDL 出力には不要な表領域・ストレージ情報が含まれることがあります。SET_TRANSFORM_PARAM で出力形式をカスタマイズできます。

セッション全体のトランスフォーム設定をカスタマイズする
-- セッションレベルの設定(このセッション内の全 GET_DDL に適用される)
BEGIN
    -- セミコロン(;)を末尾に付ける(デフォルト: FALSE)
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        transform_handle => DBMS_METADATA.SESSION_TRANSFORM,
        name             => 'SQLTERMINATOR',
        value            => TRUE
    );

    -- 表領域情報を除外する(環境依存の情報を含めない)
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        transform_handle => DBMS_METADATA.SESSION_TRANSFORM,
        name             => 'TABLESPACE',
        value            => FALSE
    );

    -- ストレージ情報を除外する
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        transform_handle => DBMS_METADATA.SESSION_TRANSFORM,
        name             => 'STORAGE',
        value            => FALSE
    );

    -- セグメント属性情報を除外する(PCTFREE・PCTUSED など)
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        transform_handle => DBMS_METADATA.SESSION_TRANSFORM,
        name             => 'SEGMENT_ATTRIBUTES',
        value            => FALSE
    );
END;
/

-- 設定を適用した後に DDL を取得
SELECT DBMS_METADATA.GET_DDL('TABLE', 'EMPLOYEES') FROM DUAL;

-- 設定を初期値に戻す
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'DEFAULT');

GET_DEPENDENT_DDL で依存オブジェクトを取得する

テーブルに付随するトリガー・権限・参照整合性制約などはGET_DEPENDENT_DDL で取得できます。

依存オブジェクトの DDL を取得する
-- テーブルのトリガーをまとめて取得
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('TRIGGER', 'EMPLOYEES') FROM DUAL;

-- テーブルへの権限付与(GRANT 文)を取得
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('OBJECT_GRANT', 'EMPLOYEES') FROM DUAL;

-- テーブルのインデックスを取得(GET_DDL のスキーマ版)
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('INDEX', 'EMPLOYEES') FROM DUAL;

-- 外部キー制約を含む制約情報
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('REF_CONSTRAINT', 'EMPLOYEES') FROM DUAL;
-- ※ 対象テーブルの主キー/ユニークキーを参照している他テーブルの外部キー制約を取得

OPEN/FETCH/CLOSE で複数オブジェクトを一括取得する

スキーマ内のすべてのテーブル(または他のオブジェクト種別)の DDL を一括で取得したい場合はカーソルスタイルの API を使います。

スキーマ内の全テーブルの DDL を一括取得する
-- スキーマ内の全テーブルの DDL を順番に取得する
DECLARE
    v_handle NUMBER;
    v_ddl    CLOB;
BEGIN
    -- ① セッション設定(セミコロン付き・ストレージ情報なし)
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE);
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE);
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        DBMS_METADATA.SESSION_TRANSFORM, 'TABLESPACE', FALSE);

    -- ② ハンドルを OPEN(スキーマ内の全テーブルを対象に)
    v_handle := DBMS_METADATA.OPEN('TABLE');
    DBMS_METADATA.SET_FILTER(v_handle, 'SCHEMA', 'HR');  -- スキーマ名を指定

    -- ③ FETCH で1件ずつ取得
    LOOP
        v_ddl := DBMS_METADATA.FETCH_CLOB(v_handle);
        EXIT WHEN v_ddl IS NULL;   -- NULL が返ったら終了
        DBMS_OUTPUT.PUT_LINE(SUBSTR(v_ddl, 1, 200) || '...');  -- 先頭200文字を出力
    END LOOP;

    -- ④ ハンドルをクローズ
    DBMS_METADATA.CLOSE(v_handle);
END;
/
スキーマ内の指定オブジェクト種別をまとめてスクリプト出力する
-- 実用的なパターン: ビューの一覧を取得してスクリプトとして出力
DECLARE
    v_handle NUMBER;
    v_ddl    CLOB;
    v_count  NUMBER := 0;
BEGIN
    DBMS_METADATA.SET_TRANSFORM_PARAM(
        DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE);

    v_handle := DBMS_METADATA.OPEN('VIEW');
    DBMS_METADATA.SET_FILTER(v_handle, 'SCHEMA', USER);   -- 現在のスキーマ

    LOOP
        v_ddl := DBMS_METADATA.FETCH_CLOB(v_handle);
        EXIT WHEN v_ddl IS NULL;
        v_count := v_count + 1;
        DBMS_OUTPUT.PUT_LINE('-- View #' || v_count);
        DBMS_OUTPUT.PUT_LINE(DBMS_LOB.SUBSTR(v_ddl, 32767, 1));
    END LOOP;

    DBMS_METADATA.CLOSE(v_handle);
    DBMS_OUTPUT.PUT_LINE('合計 ' || v_count || ' 件のビュー DDL を取得しました');
END;
/

GET_DDL で指定できる主要なオブジェクト種類(object_type 一覧)

object_type 対象オブジェクト
TABLE テーブル(CREATE TABLE 文)
INDEX インデックス(CREATE INDEX 文)
VIEW ビュー(CREATE OR REPLACE VIEW 文)
SEQUENCE シーケンス(CREATE SEQUENCE 文)
PROCEDURE ストアドプロシージャ
FUNCTION ファンクション
PACKAGE パッケージ仕様部
PACKAGE_BODY パッケージ本体
TRIGGER トリガー
TYPE 型(オブジェクト型)
SYNONYM シノニム
DB_LINK データベースリンク
TABLESPACE 表領域(DBA権限必要)
USER ユーザー(DBA権限必要)
ROLE ロール(DBA権限必要)

取得した DDL をファイルに書き出す場合は UTL_FILE が活用できます。詳細は UTL_FILE完全ガイドを参照してください。インデックスの DDL 取得方法の詳細は インデックス情報を取得する完全ガイドも参照してください。