Подтвердить что ты не робот

Как сделать dbms_metadata.get_ddl более привлекательным/полезным

Я создаю пакет для создания DDL объектов в моей схеме (вы разбираете имя объекта и возвращаете clob с DDL), поэтому я могу сгенерировать файлы и поместить их прямо в SVN.

Я использую dbms_metadata.get_ddl, и он отлично работает для всех объектов, кроме таблиц/материализованных представлений.

Если я создаю таблицу как:

create table stackoverflow
     ( col_1 varchar2(64)
     , col_2 number
     , col_3 date);

create index idx_test on stackoverflow(col_1);

alter table stackoverflow add constraint ui_test unique (col_2) using index;

И создайте DDL с помощью:

begin
   dbms_output.put_line(dbms_metadata.get_ddl( object_type => 'TABLE'
                                             , name => 'STACKOVERFLOW')
                        );
end;

Это дает нам:

CREATE TABLE "TEST_SCHEMA"."STACKOVERFLOW" 
 (  "COL_1" VARCHAR2(64), 
  "COL_2" NUMBER, 
  "COL_3" DATE, 
   CONSTRAINT "UI_TEST" UNIQUE ("COL_2")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
STORAGE(INITIAL 131072 NEXT 131072 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS_DATA_TS"  ENABLE
 ) SEGMENT CREATION IMMEDIATE 
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
NOCOMPRESS LOGGING
STORAGE(INITIAL 131072 NEXT 131072 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS_DATA_TS" 

Чтобы принять все соответствующие индексы, мы можем использовать:

begin
   dbms_output.put_line(dbms_metadata.get_dependent_ddl( object_type => 'INDEX'
                                                       , base_object_name => 'STACKOVERFLOW'));
end;

иметь:

CREATE INDEX "TEST_SCHEMA"."IDX_TEST" ON "MF"."STACKOVERFLOW" ("COL_1") 
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
STORAGE(INITIAL 131072 NEXT 131072 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS_DATA_TS" 
CREATE UNIQUE INDEX "TEST_SCHEMA"."UI_TEST" ON "MF"."STACKOVERFLOW" ("COL_2") 
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
STORAGE(INITIAL 131072 NEXT 131072 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS_DATA_TS" 

Я хочу создать файл, содержащий: создать таблицу, ограничения, индексы, гранты (иметь один файл со всем необходимым определением) и использовать dbms_metadata для меня это не представляется возможным.

Мои проблемы с выходом:

  • Двойная цитата с именем

  • Название схемы внутри DDL затрудняет компиляцию одного и того же DDL во многих схемах. Чтобы исправить это, нам нужно создать некоторые из регулярных выражений или добавить что-то вроде следующего, чтобы исправить это:

     dbms_metadata.SET_REMAP_PARAM(dbms_metadata.SESSION_TRANSFORM,'REMAP_SCHEMA','TEST_SCHEMA','');
    

    но вы должны добавить еще 8 строк:

    hOpenOrig0 := DBMS_METADATA.OPEN('TABLE');
    DBMS_METADATA.SET_FILTER(hOpenOrig0,'NAME',p_object_name);
    DBMS_METADATA.SET_FILTER(hOpenOrig0,'SCHEMA',get_table.owner);
    tr := dbms_metadata.add_transform(hOpenOrig0, 'MODIFY');
    hTransDDL := DBMS_METADATA.ADD_TRANSFORM(hOpenOrig0,'DDL');
    dbms_metadata.set_remap_param(tr, name => 'REMAP_SCHEMA', old_value => user, new_value => '');
    get_package_spec.ddl := DBMS_METADATA.FETCH_CLOB(hOpenOrig0);
    DBMS_METADATA.CLOSE(hOpenOrig0);
    
  • В один и тот же момент нет способа извлечения ограничений (которые используют индексы) и индексов. Вы не можете конкатенировать вывод из-за повторения определения ui_test. Да, есть возможность удалить ограничения из get_ddl, но мы теряем ограничения/проверки.

  • Как разработчик PL/SQL создает выходные данные

    -- Create table
    create table STACKOVERFLOW
    (
      col_1 VARCHAR2(64),
      col_2 NUMBER,
      col_3 DATE
    )
    tablespace USERS_DATA_TS
      pctfree 10
      pctused 40
      initrans 1
      maxtrans 255
      storage
      (
        initial 128K
        next 128K
        minextents 1
        maxextents unlimited
        pctincrease 0
      );
    -- Create/Recreate indexes 
    create index IDX_TEST on STACKOVERFLOW (COL_1)
      tablespace USERS_DATA_TS
      pctfree 10
      initrans 2
      maxtrans 255
      storage
      (
        initial 128K
        next 128K
        minextents 1
        maxextents unlimited
        pctincrease 0
      );
    -- Create/Recreate primary, unique and foreign key constraints 
    alter table STACKOVERFLOW
      add constraint UI_TEST unique (COL_2)
      using index 
      tablespace USERS_DATA_TS
      pctfree 10
      initrans 2
      maxtrans 255
      storage
      (
        initial 128K
        next 128K
        minextents 1
        maxextents unlimited
        pctincrease 0
      );
    

Кто-нибудь знает, как создать выход, похожий на PL/SQL Developer? Я думаю, они создали XML-парсер dbms_metadata.get_xml), чтобы создать более красивую версию (отступы, порядок, все в хорошем месте, готовые к компиляции в любом месте).

Конечно, я могу играть с регулярными выражениями или user_indexes, но это не точка.

пс. DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'PRETTY',true); - странное определение, что "красиво".

4b9b3361

Ответ 1

dbms_metadata.get_dll получает объект oracle как xml и затем преобразует его с помощью xslt в ddl script.

Список полезной таблицы select table_name from all_tables where table_name like 'META%'.

  • METASTYLESHEET - отображает таблицу стилей на имя

  • METAXSL $- сопоставляет XMLTAG с именем таблицы стилей - привяжите его к 1-й таблице

  • METAVIEW $- сопоставляет тип объекта с XMLTAG - ссылку на вторую таблицу
  • METAXSLPARAM $- таблица поиска для фильтров преобразования, доступных для каждого типа объекта и типа преобразования.

Для таблицы oracle использует kutable для xml для ddl для индекса oracle использует kuindex... и т.д.

При настройке параметров вы можете изменить поведение преобразования. Чтобы найти полезную проверку параметров таблицы METAXSLPARAM $или найти ее в документах таблиц стилей. EMIT_SCHEMA - я нашел в kucommon xslt

EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'EMIT_SCHEMA',false);  --undocumented remove schema
EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SEGMENT_CREATION',false);  --undocumented remove segement creation
EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'CONSTRAINTS_AS_ALTER',true);
select dbms_metadata.get_ddl( object_type => 'TABLE' , name => 'STACKOVERFLOW') from dual;

Ответ 2

Могу ли я предложить вам использовать expdp/impdp для целей экспорта ddl.

Схема экспорта: faydin со следующим expdp.

expdp userid=faydin/***** directory=ORA_TMP_DIR reuse_dumpfiles=y content=METADATA_ONLY exclude=STATISTICS schemas=faydin dumpfile=metadata.dmp

Получить ddl в ddl.sql для user : faydin remapped as: faydin3 с помощью impdp

impdp userid=faydin/***** directory=ORA_TMP_DIR dumpfile=metadata.dmp sqlfile=ddl.sql remap_schema=faydin:faydin3

Импортировать схему в db, удалив фразу sqlfile=ddl.sql в команде impdp.