Script Oracle DDL de manera automatizada


14

Oracle SQL Developer puede exportar DDL a través de Tools -> Database Export...Esto funciona muy bien, pero requiere intervención manual.

Lo sé DBMS_METADATA.get_ddl(), pero he descubierto que la exportación no es perfecta. Me encontré con problemas en los que el DBMS_METADATADDL exportado no era utilizable sin solucionar primero problemas como saltos en el medio de una palabra clave, y peor. Sin embargo, si alguien conoce una forma de exportar DDL a través de DMBS_METADATAeso que puede ejecutarse sin arreglos manuales, esa sería una gran solución también.

Básicamente, estoy buscando una forma automática / programable para exportar DDL idéntico a lo que se exporta a través de la forma manual.

¿Cómo puedo hacer eso?


1
¿Está ejecutando DBMS_METADATA a través de SQLplus? ¿Tiene el ancho de línea establecido> 80?
David Mann el

Estoy usando SQLPlus. ¿Hay una mejor utilidad? ¿Quieres decir con 'set linesize 200'? Eso no hace ninguna diferencia
MatthewToday

2
Parece que otros también tuvieron problemas. Error en versiones anteriores de Oracle, y dificultad para hacer que DBMS_METADATA funcione bien en versiones posteriores. asktom.oracle.com/pls/asktom/… Mi solución no es tan buena para ti. Normalmente ejecuto DBMS_METADATA en una herramienta gráfica (como Toad) y luego corto y pego en un documento de texto. Definitivamente no es automatizable, pero parece manejar mejor las terminaciones de línea con CLOB.
David Mann

Hmmm parece que podrían estar pegadas con la forma manual por ahora entonces ... Gracias por la ayuda y el enlace aunque :)
MatthewToday

1
@David: debe establecer el ancho de la columna de salida utilizando COL, como se muestra en este ejemplo , y funcionará.
Nick Chammas

Respuestas:


5

Bueno, si sqlplus está arruinando su salida dbms_metadata.get_ddl, ¿por qué no seleccionar la salida en un CLOB y escribir el CLOB en el sistema de archivos?

p.ej

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;
/

Esto debería obtener el DDL correcto, sin que la salida se estropee. Lo único es que el script se creará en el servidor de base de datos y no en el cliente desde el que invoca sqlplus.

El script se guarda en el directorio señalado por la entrada 'DATA_PUPM_DIR' en el Servidor DB. es decir

select directory_path from all_directories where directory_name like 'DATA_PUMP_DIR';

Además, puede agregar algún tipo de iteración sobre todas las tablas / índices, etc. de un esquema, y ​​obtener un DDL de un esquema completo en poco tiempo. Lo hago todo el tiempo.


2
Tenga en cuenta que esto escribe el archivo en el sistema de archivos del servidor. Cualquiera que busque obtener el DDL en la máquina del cliente, esto no lo logrará.
Andrew Spencer

6

La razón por la que tiene problemas dbms_metadata.get_ddles porque produce CLOBs que pueden tener hasta 4 GB de tamaño. De manera predeterminada, SQL * Plus y Oracle SQL Developer truncan el texto largo para que no arrojen basura al cliente con grandes cantidades de texto.

Es muy fácil anular este comportamiento en SQL * Plus con algunos SETcomandos y obtener DDL limpio.

El script que necesitas es:

-- 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

Las siguientes transformaciones pueden ayudar. No he usado el método DBMS_XSLPROCESSOR.CLOB2FILE, pero sí los utilicé para migrar una base de datos Oracle de Solaris a Linux. No pude usar la bomba de datos debido a la versión de Oracle que estaban usando y al hecho de que usaban tipos de datos XML para los tipos de datos de columna.

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 );
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.