テーブルやインデックス・ビュー・ストアドプロシージャの 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 取得方法の詳細は インデックス情報を取得する完全ガイドも参照してください。