【问题标题】:How get copy of objects from oracle database如何从 oracle 数据库中获取对象的副本
【发布时间】:2012-01-30 08:23:44
【问题描述】:

我计划发布我们的产品。我们正在使用 Oracle 表单来开发我们的软件。

所以我有两种释放对象

  1. 前端 => Oracle 表单
  2. 后端 => Oracle 数据库程序(过程、函数和包)

发布的一个重要部分是我们需要备份,所以如果发生任何事情,我们可以使用旧版本。

顺便说一句,对于前端对象,我将使用一些批处理文件为我的前端对象创建备份,但对于后端对象,我不知道如何获取函数、过程或包的副本(规范& body) 自动。

知道如何自动完成吗?请给我建议。 我们正在使用 oracle 10g & 9i

【问题讨论】:

  • 从 ALL_SOURCE 中选择字段,其中 Name = ObjectName 将适用于除触发器之外的任何内容。 All_Triggers 中的选择字段将对触发器起作用。将这些值存储到“备份”表中,然后再用新对象覆盖您并完成。虽然我相信 DBA 有更好的方法。
  • 你没有使用源代码管理工具来管理你的代码吗?
  • @APC:我们正在使用 PVCS 来跟踪我们的版本,但我希望立即采取行动来恢复客户端的所有内容。在我的公司中,有时开发人员会在 webbex 期间应用一些包或功能,因此有时客户生产与我们的 pvcs 不同。(1 或 2 例)。你有发布的经验吗?你能给我建议吗?
  • 请 DBA 团队导出架构,您将拥有所有对象及其中数据的副本
  • 听说Oracle数据库以后可以备份和恢复。

标签: oracle oracle10g oracle9i release-management oracleforms


【解决方案1】:

(为代码块道歉)。

这是我用来处理此类问题的一些代码:

PROCEDURE DUMP_CLOB(aCLOB        IN CLOB,
                    hOutput_file IN UTL_FILE.FILE_TYPE) IS
  nCLOB_length       NUMBER;
  nCLOB_offset       NUMBER := 1;
  nMax_chunk_size    NUMBER := 32767;
  strChunk           VARCHAR2(32767);
BEGIN
  nCLOB_length := DBMS_LOB.GETLENGTH(aCLOB);

  WHILE nCLOB_offset <= nCLOB_length LOOP
    strChunk := DBMS_LOB.SUBSTR(aCLOB, nMax_chunk_size, nCLOB_offset);

    UTL_FILE.PUT(hOutput_file, strChunk);

    nCLOB_offset := nCLOB_offset + LENGTH(strChunk);
  END LOOP;

  UTL_FILE.PUT_LINE(hOutput_file, ';');
END DUMP_CLOB;

PROCEDURE DUMP_PRIVS(strOwner        IN  VARCHAR2,
                     strObject_name  IN  VARCHAR2,
                     hOutput_file    IN  UTL_FILE.FILE_TYPE) IS
BEGIN
  FOR pRow IN (SELECT *
                 FROM DBA_TAB_PRIVS p
                 WHERE p.OWNER = strOwner AND
                       p.TABLE_NAME = strObject_name)
  LOOP
    UTL_FILE.PUT_LINE(hOutput_file, 'GRANT ' || pRow.PRIVILEGE || ' ON ' ||
                                    strOwner || '.' || strObject_name ||
                                    ' TO ' || pRow.GRANTEE || ';');
  END LOOP;
END DUMP_PRIVS;

PROCEDURE DUMP_OBJECT(strOwner        IN  VARCHAR2,
                      strObject_name  IN  VARCHAR2,
                      hOutput_file    IN  UTL_FILE.FILE_TYPE)
IS
  clobDDL              CLOB;
  strCurr_object_name  VARCHAR2(100);
BEGIN
  FOR rowObject IN (SELECT *
                      FROM SYS.DBA_OBJECTS o
                      WHERE o.OWNER = strOwner AND
                            o.OBJECT_NAME = strObject_name AND
                            o.OBJECT_TYPE <> 'TABLE PARTITION')
  LOOP
    strCurr_object_name := NVL(rowObject.SUBOBJECT_NAME, rowObject.OBJECT_NAME);

    UTL_FILE.PUT_LINE(hOutput_file, '-- DDL for ' || LOWER(rowObject.OBJECT_TYPE) || ' ' ||
                                    strOwner || '.' || strCurr_object_name);

    SELECT DBMS_METADATA.GET_DDL(rowObject.OBJECT_TYPE, strCurr_object_name, strOwner) AS DDL
      INTO clobDDL
      FROM DUAL;

    DUMP_CLOB(clobDDL, hOutput_file);

    DUMP_PRIVS(strOwner, strCurr_object_name, hOutput_file);

    IF rowObject.OBJECT_TYPE = 'TABLE' THEN
      -- Indexes

      FOR aRow IN (SELECT DBMS_METADATA.GET_DDL('INDEX', i.INDEX_NAME, i.OWNER) AS clobIndex
                     FROM DBA_INDEXES I
                     WHERE I.TABLE_OWNER = strOwner AND
                           I.TABLE_NAME = strCurr_object_name)
      LOOP
        DUMP_CLOB(aRow.clobIndex, hOutput_file);
      END LOOP;  -- Indexes
    END IF;

    IF rowObject.OBJECT_TYPE IN ('TABLE', 'VIEW') THEN
      -- Triggers

      FOR aRow IN (SELECT DBMS_METADATA.GET_DDL('TRIGGER', t.TRIGGER_NAME, t.OWNER) AS clobTrigger
                     FROM DBA_TRIGGERS t
                     WHERE TABLE_OWNER = strOwner AND
                     TABLE_NAME = strCurr_object_name)
      LOOP
        DUMP_CLOB(aRow.clobTrigger, hOutput_file);
      END LOOP;  -- Triggers
    END IF;
  END LOOP;
END DUMP_OBJECT;


PROCEDURE DUMP_OBJECT(strOwner           IN  VARCHAR2,
                      strObject_name     IN  VARCHAR2,
                      strDirectory_name  IN  VARCHAR2,
                      strFilename        IN  VARCHAR2,
                      strOpen_mode       IN  VARCHAR2 DEFAULT 'w')
IS
  hOutput_file  UTL_FILE.FILE_TYPE;
BEGIN
  hOutput_file := UTL_FILE.FOPEN(location  => strDirectory_name,
                                 filename  => strFilename,
                                 open_mode => strOpen_mode);
  DUMP_OBJECT(strOwner, strObject_name, hOutput_file);
  UTL_FILE.FCLOSE(hOutput_file);
EXCEPTION
  WHEN OTHERS THEN
    UTL_FILE.FCLOSE(hOutput_file);
    RAISE;
END DUMP_OBJECT;

我建议将这些程序放入一个包中。调用 DUMP_OBJECT 获取要转储的内容。

分享和享受。

【讨论】:

  • 你能告诉我应该为 str owner 和 directory_name 放什么吗? object_name 和 filename 有什么区别?
  • strOwner 是您要转储的对象所在的架构。 strDirectory_name 是文件系统中目录的名称,可通过 UTL_FILE 访问您要在其中创建文件的目录。 strFilename 是要写入 DDL 的文件的名称。
【解决方案2】:

“在我的公司中,有时开发人员会应用一些包或功能 在 webbex 期间,因此有时客户生产与我们的不同 聚氯乙烯。”

那么将代码存储在存储库中的意义何在?测试配置有什么意义?发布管理的重点是什么?

如果这些在您客户的生产环境中捣乱的牛仔开发人员是您的员工,那么您需要对他们进行纪律处分。强制执行流程以确保仅部署经过认证的配置。如果需要紧急调整,则应将其改装到官方版本中。

如果这些开发人员真的为客户工作,那么我想你无法阻止他们。但你不必支持他们,也不必为他们的变化负责。 (除非销售合同规定您必须这样做,这不会让我感到惊讶。)

【讨论】:

  • 我同意你的观点,但相信我他们不知道公司配置管理的价值,这就是为什么有时会发生这类问题。顺便说一句,我们试图识别它们并阻止它们.. .我们的管理层不清楚如何惩罚他们......其他公司如何惩罚这种开发人员?
  • @rima - 抱歉,但就公司纪律程序向您提供建议是 方式 题外话。我的建议是:如果您的同事不了解正当程序的重要性,而您的经理现在不知道如何正确执行政策,那么也许是时候寻找新雇主了?
  • 我想,但真的在马来西亚我找不到任何 CM 工作 :( 就在美国!目前在这里工作对我来说非常有价值 :) 如果你有朋友请介绍给我: )
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 2012-04-12
  • 2018-07-19
  • 2018-10-03
  • 1970-01-01
相关资源
最近更新 更多