Skryptuj Oracle DDL w sposób zautomatyzowany

14

Oracle SQL Developer jest w stanie eksportować DDL przez Tools -> Database Export...To działa bardzo dobrze, ale wymaga ręcznej interwencji.

Wiem o tym DBMS_METADATA.get_ddl(), ale odkryłem, że eksport nie jest idealny. Natknąłem się na problemy, w których wyeksportowany DBMS_METADATADDL nie był użyteczny bez uprzedniej naprawy problemów, takich jak przerwy w środku słowa kluczowego i gorzej. Jeśli jednak ktoś zna sposób eksportowania DDL, DMBS_METADATAktóry może działać bez ręcznych poprawek, byłoby to również świetne rozwiązanie.

Zasadniczo szukam automatycznego / skryptowalnego sposobu eksportu DDL identycznego z tym, który jest eksportowany ręcznie.

Jak mogę to zrobić?

MatthewToday
źródło
1
Czy korzystasz z DBMS_METADATA przez SQLplus? Czy masz ustawioną szerokość linii> 80?
David Mann
Korzystam z SQLPlus. Czy jest lepsze narzędzie? Czy masz na myśli „set lineize 200”? To nie ma znaczenia
MatthewToday
2
Wygląda na to, że inni też mieli problemy. Błąd we wcześniejszych wersjach Oracle i trudność sprawiająca, że ​​DBMS_METADATA gra ładnie w późniejszych wersjach. asktom.oracle.com/pls/asktom/… Moje rozwiązanie nie jest dla ciebie świetne. Zazwyczaj uruchamiam DBMS_METADATA w narzędziu graficznym (takim jak Toad), a następnie wycinam i wklejam do dokumentu tekstowego. Zdecydowanie nie jest zautomatyzowany, ale wydaje się, że ładniej radzi sobie z zakończeniami linii z CLOBami.
David Mann
Hmmm wygląda na to, że na razie trzymam się ręcznego sposobu ... Dzięki za pomoc i link :)
MatthewToday
1
@ David - Musisz ustawić szerokość kolumny wyjściowej za pomocą COL, jak pokazano w tym przykładzie , i będzie działać.
Nick Chammas,

Odpowiedzi:

5

Cóż, jeśli sqlplus wkręca dane wyjściowe dbms_metadata.get_ddl, dlaczego nie wybrać danych wyjściowych w CLOB i zapisać CLOB do systemu plików.

na przykład

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

To powinno dać ci poprawny DDL, bez pomieszania danych wyjściowych. Jedyne, że skrypt zostanie utworzony na serwerze DB, a nie na kliencie, z którego wywołujesz sqlplus.

Skrypt jest zapisywany w katalogu wskazywanym przez pozycję „DATA_PUPM_DIR” na serwerze DB. to znaczy

select directory_path from all_directories where directory_name like 'DATA_PUMP_DIR';

Co więcej, możesz dodać jakąś iterację do wszystkich tabel / indeksów itp. Schematu i uzyskać natychmiastowy kompletny kod DDL schematu. Ciągle to robię.


źródło
2
Uwaga: powoduje to zapisanie pliku w systemie plików serwera. Każdy, kto chce uzyskać DDL na komputerze klienckim, nie osiągnie tego.
Andrew Spencer
6

Powodem, dla którego masz problemy, dbms_metadata.get_ddljest to, że wysyła CLOBon pliki o wielkości do 4 GB. Domyślnie SQL * Plus i Oracle SQL Developer obcinają długi tekst, aby nie niszczyły klienta dużą ilością tekstu.

Bardzo łatwo jest zastąpić to zachowanie w SQL * Plus za pomocą kilku SETpoleceń i uzyskać czysty DDL.

Potrzebny skrypt to:

-- 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;
Nick Chammas
źródło
0

Pomocne mogą być następujące transformacje. Nie użyłem metody DBMS_XSLPROCESSOR.CLOB2FILE, ale użyłem ich do migracji bazy danych Oracle z Solaris do Linux. Nie mogłem użyć pompy danych ze względu na używaną przez nich wersję Oracle i fakt, że używali typów danych XML dla typów danych kolumnowych.

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 );
Gandolf989
źródło