Oracle SQL Developerは_Tools -> Database Export...
_を介してDDLをエクスポートできます。これは非常にうまく機能しますが、手動による介入が必要です。
私はDBMS_METADATA.get_ddl()
を知っていますが、エクスポートが完全ではないことがわかりました。エクスポートされた_DBMS_METADATA
_ DDLが、キーワードの途中での中断などの問題を修正せずに使用できなかったり、さらに悪い問題が発生したりしました。ただし、誰かが_DMBS_METADATA
_を介してDDLをエクスポートする方法を知っていて、手動で修正しなくても実行できる場合、それも素晴らしい解決策になります。
基本的に、DDL identicalを手動の方法でエクスポートされるものにエクスポートする自動/スクリプト可能な方法を探しています。
どうやってやるの?
さて、sqlplusがdbms_metadata.get_ddl出力をねじ込んでいる場合は、CLOBで出力を選択し、CLOBをファイルシステムに書き込んでみませんか。
例えば.
DECLARE
data CLOB;
objType varchar2(30) := 'TABLE';
objSchema varchar2(30) := 'SCOTT';
objName varchar2(30) := 'EMP';
fname varchar2(256) := objType || '_' || objSchema || '_' || objName || '.sql';
BEGIN
SELECT dbms_metadata.get_ddl(objType,objName,objSchema) into data from dual;
DBMS_XSLPROCESSOR.CLOB2FILE(data,'DATA_PUMP_DIR',fname);
END;
/
これにより、出力が乱れることなく、正しいDDLが得られます。唯一のことは、スクリプトは、sqlplusを呼び出したクライアントではなく、DBサーバー上に作成されるということです。
スクリプトは、DBサーバーの 'DATA_PUPM_DIR'エントリが指すディレクトリに保存されます。つまり.
select directory_path from all_directories where directory_name like 'DATA_PUMP_DIR';
さらに、スキーマのすべてのテーブル/インデックスなどにある種の反復を追加して、すぐに完全なスキーマのDDLを取得できます。私はいつもそれをしています。
dbms_metadata.get_ddl
で問題が発生するのは、最大4GBのCLOB
sが出力されるためです。デフォルトでは、SQL * PlusとOracle SQL Developerは長いテキストを切り捨てるので、大量のテキストでクライアントを壊すことはありません。
いくつかのSET
コマンドを使用してSQL * Plusでこの動作をオーバーライドし、クリーンなDDLを取得するのは非常に簡単です。
必要なスクリプトは次のとおりです。
-- Run this script in SQL*Plus.
-- don't print headers or other crap
set heading off;
set echo off;
set pagesize 0;
-- don't truncate the line output
-- trim the extra space from linesize when spooling
set long 99999;
set linesize 32767;
set trimspool on;
-- don't truncate this specific column's output
col object_ddl format A32000;
spool sys_ddl.sql;
SELECT dbms_metadata.get_ddl(object_type, object_name, owner) || ';' AS object_ddl
FROM DBA_OBJECTS
WHERE
OWNER = 'SYS'
AND OBJECT_TYPE IN (
'TABLE'
, 'INDEX'
, 'SEQUENCE'
, 'VIEW'
)
ORDER BY
OWNER
, OBJECT_TYPE
, OBJECT_NAME
;
spool off;
次の変換が役立つ場合があります。 DBMS_XSLPROCESSOR.CLOB2FILEメソッドは使用していませんが、OracleデータベースをSolarisからLinuxに移行するために使用しました。彼らが使用していたOracleのバージョンと、列データ型にXMLデータ型を使用していたため、データポンプを使用できませんでした。
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'PRETTY', TRUE );
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE );
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'REF_CONSTRAINTS', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'OID', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'TABLESPACE', TRUE );