【Oracle】源环境dmp文件导入不同编码环境解决方案

本文详细介绍如何将Oracle 11g生产环境数据库同步到开发环境,包括解决数据乱码、Blob/Clob字段导入问题及特殊处理步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文中使用的Oracle版本为11g。

最近由于开发需要,要将现生产环境数据库全部同步到开发环境中(包括数据、表结构、存储过程、方法…)。但是在导入的过程中发现了以下问题:

  1. 数据库服务端编码不一致,导入之后数据为乱码。
  2. 表中存在Blob和Clob类型的字段,在导入过程中出现了表不能导入或者导入后没有数据的情况。

由于数据来源是生产库且不能随意访问,因此所有生产数据都将通过脚本晚上定时执行远程备份(脚本是之前同事留下的,离职后没有人维护又将这个烂摊子给到自己头上了)。
在查阅脚本后发现,导出的dmp文件是直接通过exp导出,没有使用到expdp(数据泵),因此在导入时需要做一些特殊处理才能完全导入,共7步下面将进行详细说明。

1 开发库中采用dba账号登录,将当前账号下的所有表描述及其字段描述导出到excel中

导出字段描述语句:

select 'comment on column '||table_name||'.'||column_name||' is '''||comments||''';' 
from dba_col_comments t 
where t.owner = 'xxx';

导出表描述语句:

select 'comment on table '||table_name||'  is '''||comments||''';' 
from dba_tab_comments t 
where t.owner = 'xxx';

查询结果可以使用PL/SQL的“Copy to Excel…”导出到Excel,如下图:
这里写图片描述

2 将生产导出的dmp文件上传到导入环境服务器,然后导出当前dmp的结构信息

imp <xe_username>/<password>@XE file=<filename.dmp> indexfile=index.sql full=y

通过上面的语句会将dmp文件中的结构信息导出成一个sql文件,里面的内容大致如下:
这里写图片描述

3 用PL/SQL打开sql文件,执行以下5步替换操作

  1. 找到: 'REM ’ 替换: ‘’
  2. 找到: ‘“原来的表空间”’ 替换: ‘“目标表空间”’
  3. 找到: ‘…’ 替换: ‘REM …’
  4. 找到: ‘CONNECT’ 替换: ‘REM CONNECT’
  5. 找到: 'REM ’ 替换: ‘–’

完成操作后执行该脚本,数据库就能够生成好表结构了。

4 执行存储过程干掉所有约束

exec MANAGE_USER_CONSTRAINTS('disable',true,true,true);

存储过程的代码如下:

CREATE OR REPLACE PROCEDURE MANAGE_USER_CONSTRAINTS(OPERATION VARCHAR2,
                                                  FK        BOOLEAN DEFAULT TRUE,
                                                  PK        BOOLEAN DEFAULT TRUE,
                                                  UK        BOOLEAN DEFAULT TRUE) IS
/**
启动和关闭约束的存储过程脚本
created by yuanzh 2015-10-22

*/

ST VARCHAR2(255);
--获取外键关系
CURSOR R IS SELECT TABLE_NAME, CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'R';
--获取主键
CURSOR P IS SELECT TABLE_NAME, CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'P' AND INSTR(CONSTRAINT_NAME,'BIN') = 0;
--获取唯一索引
CURSOR U IS SELECT TABLE_NAME, CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'U';

BEGIN
--如果参数中是disable,关闭约束的情况下
IF UPPER(OPERATION) IN ('DROP', 'DISABLE') THEN
  --先执行外键约束的关闭
  IF FK THEN
          FOR E IN R LOOP
              BEGIN
                   ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
                   EXECUTE IMMEDIATE (ST);
              EXCEPTION WHEN OTHERS THEN
                   NULL;
                   DBMS_OUTPUT.PUT_LINE(ST);
              END;
          END LOOP;
  END IF;
  
  --执行主键约束的关闭
  IF PK THEN
     -- 先关闭外键
     FOR E IN R LOOP
         BEGIN
              ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
              EXECUTE IMMEDIATE (ST);
         EXCEPTION WHEN OTHERS THEN
                   NULL;
                   DBMS_OUTPUT.PUT_LINE(ST);
         END;
     END LOOP;
     --再关闭主键
     FOR E IN P LOOP
         BEGIN
              ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
              EXECUTE IMMEDIATE (ST);
          EXCEPTION WHEN OTHERS THEN
                     NULL;
                     DBMS_OUTPUT.PUT_LINE(ST);
           END;
      END LOOP;
  END IF;
  
  --执行唯一约束的关闭
  IF UK THEN
     FOR E IN U LOOP
           BEGIN
              ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
              EXECUTE IMMEDIATE (ST);
           EXCEPTION WHEN OTHERS THEN
                     NULL;
                     DBMS_OUTPUT.PUT_LINE(ST);
           END;
      END LOOP;
  END IF;

--若是启用约束的时候  
ELSIF UPPER(OPERATION) IN ('ENABLE') THEN
  --先启用主键
  IF PK THEN
     FOR E IN P LOOP
         BEGIN
              ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
              EXECUTE IMMEDIATE (ST);
        EXCEPTION WHEN OTHERS THEN
                     NULL;
                     DBMS_OUTPUT.PUT_LINE(ST);
         END;
      END LOOP;
  END IF;
  
  --启用外键
  IF FK THEN
  --先主键启动
     FOR E IN P LOOP
         BEGIN
              ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
              EXECUTE IMMEDIATE (ST);
        EXCEPTION WHEN OTHERS THEN
                     NULL;
                     DBMS_OUTPUT.PUT_LINE(ST);
         END;
      END LOOP;
    
    --在外键启动
    FOR E IN R LOOP
         BEGIN
             ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
             EXECUTE IMMEDIATE (ST);
        EXCEPTION WHEN OTHERS THEN
                     NULL;
                     DBMS_OUTPUT.PUT_LINE(ST);
         END;
      END LOOP;
  END IF;
  
  --启用唯一约束
  IF UK THEN
        FOR E IN U LOOP
            BEGIN
                ST := 'ALTER TABLE ' || E.TABLE_NAME || ' ' || OPERATION || ' CONSTRAINT ' || E.CONSTRAINT_NAME;
                EXECUTE IMMEDIATE (ST);
            EXCEPTION WHEN OTHERS THEN
                         NULL;
                         DBMS_OUTPUT.PUT_LINE(ST);
             END;
      END LOOP;
  END IF;
ELSE
  DBMS_OUTPUT.PUT_LINE('THE FIRST PARAMETER OF THE PROCEDURE MUST BE DROP OR ENABLE OR DISABLE');
END IF;
END;
 

5 执行imp导入

imp xxx/abc@se file=xxx220151020_235000.dmp fromuser=fuser touser=tuser ignore=y grants=n constraints=n rows=y buffer=80000000

6 导入完成之后再重新执行刚才的存储过程开启约束

exec MANAGE_USER_CONSTRAINTS('enable',true,true,true);

7 返回第一点中数据提取的excel,将里面的脚本在Command窗口下执行即可

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kida 的技术小屋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值