如何从oracle数据库中获取对象的副本

发布于 2024-12-23 13:29:23 字数 339 浏览 7 评论 0原文

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

所以我有两种类型的对象用于发布

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

发布的重要部分之一是我们需要备份,以便在发生任何情况时我们可以使用旧版本。

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

知道我怎样才能自动完成它吗?请给我建议。 我们正在使用 Oracle 10g & 9i

I have plan to do a release for our product. we are using Oracle forms to develop our software.

So I have two type of object for release

  1. Front-end => Oracle forms
  2. Back-end => Oracle Database Program (Procedure, function and Package)

One of the important part of release is we need to have a back up so if any thing happen we can use the older version.

By the way, for front end object I will use some batch file to create a back up for my front end objects but for Back-end object I dont know how I can get a copy of function, procedure or package(spec & body) automatically.

Any idea how I can do it automatically? please advice me.
we are using oracle 10g & 9i

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

樱娆 2024-12-30 13:29:23

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

在存储库中存储代码有什么意义?测试配置有什么意义?发布管理有什么意义?

如果这些捣乱客户生产环境的牛仔开发人员是您需要的员工强制执行流程以确保仅部署经过认证的配置,如果需要进行紧急调整,则应将这些

配置改装到正式版本中,那么我想您无法阻止它们。不必支持他们,而你不必对他们的变化负责(除非销售合同规定你必须这样做,这不会让我感到惊讶。)

"In my company sometimes developer apply some package or function
during the webbex so sometimes customer production is not same as our
pvcs."

So what is the point of storing code in a repository? What is the point of testing a configuration? What is the point of release management?

If these cowboy developers who muck around with your customers' production environments are your staff you need to discipline them. Enforce process to guarantee that only certified configurations are deployed. If emergency tweaks are required these should be retrofitted into the official build.

If these developers actually work for the customer, then I suppose you cannot stop them. But you don't have to support them, and you don't have to be responsible for their changes. (unless the sales contract says you have to, which wouldn't surprise me.)

(对代码块表示歉意)。

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

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 获取您想要转储的内容。

分享并享受。

(Apologies for the code-blob).

Here's some code I've used to handle issues like this:

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;

I suggest putting these procedures into a package. Call DUMP_OBJECT for the things you want dumped.

Share and enjoy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文