如何最好地重新创建 Oracle 数据库?

Posted

技术标签:

【中文标题】如何最好地重新创建 Oracle 数据库?【英文标题】:How best can I recreate an Oracle database? 【发布时间】:2014-10-10 15:33:55 【问题描述】:

Oracle 11gR2(x86 Windows):

我有一个包含 250 个带有索引和约束的表的数据库。我需要在新数据库中重新创建这些表、索引和约束并加载数据。我需要知道如何在 SQL Plus 和/或 SQL Developer 中执行以下操作,除非有一个神奇的实用程序可以自动执行所有这些操作。提前致谢!

    从 250 个表中卸载(导出)所有数据。

    为 250 个表创建一个包含 CREATE TABLE 语句的 sql 脚本文件。

    为 250 个表创建一个包含 CREATE INDEX 语句的 sql 脚本文件。

    为 250 个表创建一个包含 ALTER TABLE ADD CONSTRAINT 语句的 sql 脚本文件。

    运行脚本以在新数据库中创建表。

    将导出的数据加载到新数据库的表中。

    运行脚本以创建所有索引。

    运行脚本以添加所有约束。

编辑:我已连接到远程桌面,该桌面链接到 Windows Server 2008 上的源数据库。远程仅安装了 Oracle 客户端。出于安全原因,我不允许直接从本地计算机链接到 Win Server,所以我可以将整个源数据库转储到远程然后将其压缩到本地目标计算机吗?我正在尝试在我的计算机上复制整个数据库。

【问题讨论】:

【参考方案1】:

从 Oracle 10g 开始,您可以使用 Data Pump command-line clients expdbimpdb 将数据和/或模式从一个数据库导出/导入到另一个数据库。事实上,这两个命令行实用程序只是 “使用 DBMS_DATAPUMP PL/SQL 包中提供的过程来执行导出和导入命令,使用在命令行中输入的参数的包装器。” i> (引用自 Oracle 的文档)

根据您的需要,您必须创建一个目录,然后使用 expdb 生成数据库的完整转储:

SQL> CREATE OR REPLACE DIRECTORY dump_dir AS '/path/to/dump/folder/';
sh$ expdp system@db10g full=Y directory=DUMP_DIR dumpfile=db.dmp logfile=db.log

由于转储是使用某种二进制格式编写的,因此您必须使用相应的导入实用程序来(重新)导入您的数据库。基本上将上述命令中的expdb替换为impdb

sh$ impdp system@db10g full=Y directory=DUMP_DIR dumpfile=db.dmp logfile=db.log

对于简单的表转储,请改用该版本:

sh$ expdp sylvain@db10g tables=DEPT,EMP directory=DUMP_DIR dumpfile=db.dmp logfile=db.log

如您所见,只要您有权访问给定目录 (GRANT READ, WRITE ON DIRECTORY dump_dir TO sylvain;),就可以将其与标准用户帐户一起使用。


详细使用说明见 http://www.oracle-base.com/articles/10g/oracle-data-pump-10g.php

【讨论】:

还有一个因素:源数据库位于远程系统上,我需要在本地计算机上重新创建该数据库。我可以将整个 \oradata 文件夹保存在 Dropbox 中并用它替换我的 \oradata 吗? @Frank 只是移动/oradata 文件夹?我不能说,我从来没有这样做过。但是,如果您有权访问该文件夹,您仍然可以使用expdb 将您的数据库转储到那里,并仅将转储文件复制到您的系统,以便使用impdb 重新导入。 感觉对我来说更安全。 我刚刚使用 Oracle Data Modeler 的“生成 DDL”选项来创建单独的 sql 脚本文件,以创建表、索引和 PK/FK 约束。唯一的问题是它为每个表创建了单独的脚本文件,而不是为所有创建表创建一个脚本文件、一个用于创建所有索引的脚本文件和一个用于所有约束的 scipt 文件:( 我正在使用 Winx64,所以我想我可以将文件连接成一个。 仅供参考,源数据库和目标数据库都在 Windows 平台上,因此除了使用反斜杠作为目录路径之外,我假设您的 unix shell 示例中的 expdp/impdb 命令对于 DOS cmd 保持不变shell?.. 我尝试在基于浏览器的数据库控制实用程序中使用数据泵,但无法正常工作。 @Frank 你应该彻底研究expdb 的文档。它可以为所欲为。对于一个简单的表转储,我认为您不需要高级权限——您的用户帐户可能就足够了。【参考方案2】:

如果您可以创建从本地数据库到当前包含数据的数据库的数据库链接,则可以使用DBMS_DATAPUMP 包来复制整个架构。这是可从数据库中调用的 Datapump 接口(如@Sylvain Leroux 所述)。

DECLARE
   dph NUMBER;
   source_schema VARCHAR2 (30) := 'SCHEMA_TO_EXPORT';
   target_schema VARCHAR2 (30) := 'SCHEMA_TO_IMPORT';
   job_name VARCHAR2 (30) := UPPER ('IMPORT_' || target_schema);
   p_parallel NUMBER := 3;
   v_start TIMESTAMP := SYSTIMESTAMP;
   v_state VARCHAR2 (30);
BEGIN
   dph :=
      DBMS_DATAPUMP.open ('IMPORT',
                          'SCHEMA',
                          'DB_LINK_NAME',
                          job_name);
   DBMS_OUTPUT.put_line ('dph = ' || dph);
   DBMS_DATAPUMP.metadata_filter (dph,
                                  'SCHEMA_LIST',
                                  '''' || source_schema || '''');
   DBMS_DATAPUMP.metadata_remap (dph,
                                 'REMAP_SCHEMA',
                                 source_schema,
                                 target_schema);
   DBMS_DATAPUMP.set_parameter (dph, 'TABLE_EXISTS_ACTION', 'REPLACE');
   DBMS_DATAPUMP.set_parallel (dph, p_parallel);
   DBMS_DATAPUMP.start_job (dph);
   DBMS_DATAPUMP.wait_for_job (dph, v_state);
   DBMS_OUTPUT.put_line ('Export/Import time: ' || (SYSTIMESTAMP - v_start));
   DBMS_OUTPUT.put_line ('Final state: ' || v_state);
END;

上面的脚本实际上复制并重命名了模式。如果您想保留相同的架构名称,我相信您只需删除 metadata_remap 调用即可。

【讨论】:

【参考方案3】:

SQL Developer 可以通过创建带有formatted query result 的INSERT 语句来帮助解决#1:

Select /*insert*/ * 
from My_Table;

【讨论】:

我不知道这适用于什么数据库,但肯定不是 Oracle。 @Allan 这是 SQL Developer 特有的功能,是问题中提到的工具之一。这是一个很好的功能,尽管我怀疑它的效果和数据泵一样好,而且它只解决了其中一个问题。

以上是关于如何最好地重新创建 Oracle 数据库?的主要内容,如果未能解决你的问题,请参考以下文章

请问oracle数据库的数据库备份有几种方式?哪种最好用

如何在 oracle 9i 中最好地拆分 csv 字符串

jQuery.ajax() - 如何最好地处理超时?

Postgres:在从 bash 脚本重新创建/重新填充之前清除整个数据库

SQL:如何最好地查询历史表以创建特定日期的快照概览

delphi 三层架构如何调用oracle 存储过程,应该使用哪个部件,最好有实例