以自动化方式编写Oracle DDL脚本


14

Oracle SQL Developer能够通过Tools -> Database Export...此方式导出DDL,效果很好,但是需要手动干预。

我知道DBMS_METADATA.get_ddl(),但是发现导出并不完美。我遇到的问题是,导出的DBMS_METADATADDL如果不首先解决诸如关键字中间的中断以及更糟糕的问题之类的问题就无法使用。但是,如果任何人都知道DMBS_METADATA可以通过导出导出DDL的方法而无需手动修复,那也将是一个很好的解决方案。

基本上,我正在寻找一种自动/可脚本化的方式来导出DDL ,该方式通过手动方式导出的方式相同。

我怎样才能做到这一点?


1
您是否通过SQLplus运行DBMS_METADATA?您的线宽设置是否大于80?
大卫·曼

我正在使用SQLPlus。有更好的工具吗?您是说“设置行大小为200”吗?这没什么差别
MatthewToday

2
似乎其他人也有问题。Oracle早期版本中的错误,并且难以使DBMS_METADATA在更高版本中很好地发挥作用。asktom.oracle.com/pls/asktom / ...我的解决方案对您而言并不理想。我通常在图形工具(如Toad)中运行DBMS_METADATA,然后将其剪切并粘贴到文本文档中。绝对不是自动化的,但它似乎可以更好地处理CLOB的行尾。
大卫·曼

嗯,看来我现在可能
仍会继续

1
@David-您需要使用设置输出列的宽度COL,如本示例所示,它将起作用。
Nick Chammas 2012年

Answers:


5

好吧,如果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,而不会弄乱输出。唯一的是,该脚本将在DB服务器上而不是在调用sqlplus的客户端上创建。

该脚本将保存在DB Server上“ DATA_PUPM_DIR”条目指向的目录中。即

select directory_path from all_directories where directory_name like 'DATA_PUMP_DIR';

而且,您可以在模式的所有表/索引等上添加某种迭代,并立即获得完整模式的DDL。我一直都在做。


2
注意,这会将文件写入服务器的文件系统。希望在客户端计算机上获得DDL的任何人都无法实现。
Andrew Spencer 2014年

6

您遇到问题的原因dbms_metadata.get_ddl是它输出CLOB的最大大小为4GB。默认情况下,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;

0

以下转换可能会有所帮助。我没有使用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 );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.