【问题标题】:How to make dbms_metadata.get_ddl more pretty/useful如何使 dbms_metadata.get_ddl 更漂亮/更有用
【发布时间】:2015-11-24 15:42:26
【问题描述】:

我正在创建一个包以在我的架构中生成对象的 DDL(您解析对象名称,并返回带有 DDL 的 clob),因此我可以生成文件,并将它们直接放入 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,这对我来说似乎是不可能的。

我的输出问题是:

  1. 名字的双引号

  2. DDL 中的模式名称使我们难以跨多个模式编译相同的 DDL。为了解决这个问题,我们需要创建一些 for 的正则表达式或添加类似下面的内容可以解决这个问题:

     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);
    
  3. 无法同时提取约束(使用索引)和索引。由于ui_test 的重复定义,您无法连接输出。是的,可以选择从 get_ddl 中删除约束,但我们正在失去约束/检查。

  4. PL/SQL Developer 如何创建输出

    -- 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 的输出的方法吗?我猜他们创建了一些 dbms_metadata.get_xml 的 XML 解析器来创建一个更漂亮的版本(缩进、顺序,一切都很好,可以在任何地方编译)。

当然,我可以使用正则表达式或user_indexes,但这不是重点。

ps。 DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'PRETTY',true); 是一个奇怪的定义,什么是“漂亮”。

【问题讨论】:

  • 您可以使用 dbms_metadata.set_transform_param 删除架构前缀 - 有一个标志不显示或将架构 TEST_SCHEMA 重新映射为空。 PL/SQL Developer 不使用 dbms_metadata 来生成 ddl,所以那里没有引号。

标签: oracle ddl plsqldeveloper dbms-metadata


【解决方案1】:

dbms_metadata.get_dll 以 xml 格式获取 oracle 对象,然后通过 xslt 将其转换为 ddl 脚本。

有用的表列表select table_name from all_tables where table_name like 'META%'

  1. METASTYLESHEET - 将样式表映射到其名称

  2. METAXSL$ - 将 XMLTAG 映射到样式表名称 - 将其链接到第一个表

  3. METAVIEW$ - 将对象类型映射到 XMLTAG - 将其链接到第二个表
  4. 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;

【讨论】:

  • 真的很有帮助。肯定它解决了我用regexp修复的部分问题('EMIT-SCHEMA')......它并没有完全解决我的问题,但我会研究所有参数
  • 不幸的是,除了 emit-schema 并没有什么真正有趣的东西...... 调查更多我发现 get_dll 的问题更多......我想我必须直接向 Oracle 提出一些问题
  • 另请注意,SEGMENT_CREATION 似乎不再适用于 12i(此处抛出错误)。此外,我想念COMMENT ONget_ddl - 加上它激怒了多个语句(CREATE TABLE ... ALTER TABLE)是用CONSTRAINTS_AS_ALTER 生成的,但没有正确分隔(没有找到一个分号)。是否缺少另一个参数,例如dbms_metadata.set_transform_param (dbms_metadata.session_transform, 'SQLTERMINATOR', true);? ;)
  • 我不知道。我从未接触过 oracle 12:D
  • 很公平 :) 我通常建议我的客户跳过 R1 并等待 R2(更稳定),但我当前的客户在我到达之前就已经决定了 ;) 仍然:您可能希望包括 @ 987654332@ 设置你的答案,所以逆向工程的代码是可执行的。
【解决方案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

使用 impdp 为 user : faydin remapped as: faydin3 获取 ddl.sql 中的 ddl

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

通过删除 impdp 命令中的sqlfile=ddl.sql 短语将架构导入数据库。

【讨论】:

    猜你喜欢
    • 2016-05-29
    • 2021-06-02
    • 2020-11-21
    • 2020-02-13
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    相关资源
    最近更新 更多