【问题标题】:exporting db objects for version control导出数据库对象以进行版本控制
【发布时间】:2015-02-04 06:26:41
【问题描述】:

我们正在为我们的项目实施版本控制。作为其中的一部分,我们需要检查所有 DB 对象。我们有表、过程、函数、包、视图和物化视图。问题是有很多对象,我们需要明智地放置源代码文件。例如有表 T1、T2、T3,我们需要文件 Table_T1.txt,其中包含所有对象的 T1 定义(列定义、表的索引和授权)等等。

我知道元数据表,例如 DBA_VIEWSdba_sourceDBMS_METADATA.GET_DDL 等,我可以在其中找到所需的信息 但是如何明智地提取该信息对象。 目前我们在哪里工作我们正在获取特定对象的全部信息,然后将其分离(剪切 - 粘贴)到不同的文件中。有什么聪明的方法可以解决这个问题吗?

数据库 - Oracle 10g

【问题讨论】:

  • 我开始为每个对象准备脚本来实现这一点。然而,我的一位同事发现了使用蟾蜍的简单方法。对于其他人,如果您使用的是 toad,那么当您转到模式 - > 并选择对象名称并右键单击时,会有一个选项(选择选项作为创建表)。它可能非常不同版本。希望这对大家有帮助。

标签: sql oracle oracle10g ddl database-metadata


【解决方案1】:

但是如何明智地提取该信息对象。

正确传递参数。然后,您可以自定义您的输出。

DBMS_METADATA.GET_DDL (object_type, object_name, object_owner)

例如,获取用户 SCOTT 中所有表的 METADATA

SQL> conn scott/tiger@pdborcl;
Connected.
SQL> set long 200000
SQL> select dbms_metadata.get_ddl('TABLE',t.table_name, 'SCOTT') from US

DBMS_METADATA.GET_DDL('TABLE',T.TABLE_NAME,'SCOTT')
------------------------------------------------------------------------

  CREATE TABLE "SCOTT"."DEPT"
   (    "DEPTNO" NUMBER(2,0),
        "DNAME" VARCHAR2(14),
        "LOC" VARCHAR2(13),
         CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"


  CREATE TABLE "SCOTT"."EMP"
   (    "EMPNO" NUMBER(4,0),
        "ENAME" VARCHAR2(10),
        "JOB" VARCHAR2(9),
        "MGR" NUMBER(4,0),
        "HIREDATE" DATE,
        "SAL" NUMBER(7,2),
        "COMM" NUMBER(7,2),
        "DEPTNO" NUMBER(2,0),
         CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE,
         CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO")
          REFERENCES "SCOTT"."DEPT" ("DEPTNO") ENABLE
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"


  CREATE TABLE "SCOTT"."BONUS"
   (    "ENAME" VARCHAR2(10),
        "JOB" VARCHAR2(9),
        "SAL" NUMBER,
        "COMM" NUMBER
   ) SEGMENT CREATION DEFERRED
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS LOGGING
  TABLESPACE "USERS"


  CREATE TABLE "SCOTT"."SALGRADE"
   (    "GRADE" NUMBER,
        "LOSAL" NUMBER,
        "HISAL" NUMBER
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"

因此,这为我提供了 SCOTT 架构中所有表的 DDL

同样,您可以对所有其他对象执行相同的操作,例如 INDEXESROLES 等。

要在文本文件中获取 DDL,只需使用 SPOOL。因此,您只需要针对不同对象类型的单独脚本在各自的文本文件中进行后台处理。

【讨论】:

  • 谢谢拉利特。我之前也试过这个,如果你看到它会给我一个 DDL 的文本文件,其中所有信息都可用。我们再次明智地削减信息表。索引位于不同的位置,这些表的授权也是如此。在上面的示例中,SCOTT.BONUS 应该存在于 Table_BONUS.txt 文件中 - 该文件应该包含有关“BONUS”表以及 DDL 的索引和授权的信息。如果架构中有 500 个表,那么我们需要 500 个不同的文本文件。
  • 那么问题出在哪里?在编程中做到这一点。编写您自己的 PL/SQL 脚本以动态完成。
  • 在 DDL 级别实现控制版本的一种可能方法是开发我们的解决方案,基于 DBMS_METADATA 来提取 DDL,并基于 DBMS_METADATA_DIFF(在 +11gR1 上)来提取两个对象之间的差异。
  • 我希望 OP 提出他真正关心的问题。几乎没有什么是不可能的。
【解决方案2】:

简单的事实是,您不能像对待 Java、C# 或其他文件一样对待数据库对象。

有很多原因,我将仅举几例:

文件本地存储在开发人员的 PC 上,他/他所做的更改不会影响其他开发人员。同样,开发人员也不会受到同事所做更改的影响。在数据库中(通常)情况并非如此,开发人员共享相同的数据库环境,因此提交给数据库的任何更改都会影响其他人。

使用签入/提交更改等(取决于您使用的源代码控制工具)来发布代码更改。此时,来自开发人员本地目录的代码被插入到源代码控制存储库中。想要获取最新代码的开发人员需要从源代码管理工具中请求它。在数据库中,更改已经存在并影响其他数据,即使它没有签入到存储库中。

在文件签入期间,源代码控制工具会执行冲突检查,以查看在您修改本地副本期间,同一文件是否被其他开发人员修改和签入。再次在数据库中没有检查这个。如果您从本地 PC 更改程序,同时我使用本地 PC 的代码修改相同的程序,那么我们会覆盖彼此的更改。

代码的构建过程是通过将代码的标签/最新版本放到一个空目录中然后执行构建-编译来完成的。输出是我们复制和替换现有的二进制文件。我们不在乎以前的情况。在数据库中,我们无法重新创建数据库,因为我们需要维护数据!部署还会执行在构建过程中生成的 SQL 脚本。

在执行 SQL 脚本(使用 DDL、DCL、DML(用于静态内容)命令)时,您假设环境的当前结构与创建脚本时的结构相匹配。如果没有,那么您的脚本可能会在您尝试添加已存在的新列时失败。

将 SQL 脚本视为代码并手动生成它们会导致语法错误、数据库依赖错误、无法重用的脚本,从而使开发、维护和测试这些脚本的任务变得复杂。此外,这些脚本运行的环境可能与您想运行的环境不同。

有时版本控制存储库中的脚本与被测试对象的结构不匹配,然后在生产中会发生错误!

还有很多,但我想你明白了。

我发现可行的方法如下:

使用强制版本控制系统对数据库对象强制执行签出/签入操作。这将确保版本控制存储库与签入的代码匹配,因为它在签入操作中读取对象的元数据,而不是作为手动完成的单独步骤

使用影响分析,利用基线作为比较的一部分来识别冲突并确定更改(在比较源代码控制存储库和数据库之间的对象结构时)是否是源自开发的真正更改或更改起源于不同的路径,然后应该跳过它,例如不同的分支或紧急修复。

我写的一篇文章发表在here,欢迎阅读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-25
    • 2010-10-01
    • 1970-01-01
    • 2010-11-20
    • 2017-03-22
    • 2019-08-10
    • 1970-01-01
    相关资源
    最近更新 更多