目标数据库:Oracle Database 10g Enterprise Edition Release 10.2.0.3.0

源数据库  : Oracle Database 11g Enterprise Edition Release 11.2.0.1.0

1.首先想到的是用expdp,impdp。

通过交流发现无法得到源数据库的操作系统密码,这样一来expdp,impdp就不好使了。

2.其次想到的是用plsql developer 来导出数据,但是导出的时候报错了。

放弃此种方法。

3.由于数据量不是很大,考虑使用数据库链的方式来完成。

a.在目标数据库上创建数据库链,链接到目标数据库。

create public database link
  to_168_bi22 connect to "bi41" identified by "bi41" using
'(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST =172.21.1.68)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)';

b.得到用户对象的定义语句 dbms_metadata.get_ddl('TABLE','ACT_GE_BYTEARRAY')

在此纠结了一下,是直接用过程脚本来创建表,还是先生成建表语句,之后再循环灌数据。

c.选择先创建用户对象,之后再插入数据。

这个选择给后续的数据插入带来了一些麻烦,就是索引和约束,特别是外键约束。

在脚本中加入了禁用约束的语句

FOR i IN (SELECT table_name, constraint_name --disable first the foreign key
FROM user_constraints
WHERE constraint_type = 'R'
AND status = 'ENABLED') LOOP
EXECUTE IMMEDIATE 'alter table "' || i.table_name || '" disable constraint ' ||
i.constraint_name;
END LOOP i;
FOR i IN (SELECT table_name, constraint_name -- then disable all constraints
FROM user_constraints
WHERE status = 'ENABLED') LOOP
EXECUTE IMMEDIATE 'alter table "' || i.table_name || '" disable constraint ' ||
i.constraint_name;
END LOOP i;

感觉OK的时候,又报错了。

ERROR:  ORA-22992: cannot use LOB locators selected from remote tables

原来表中有些是LOB字段,无法通过数据链访问直接访问。

最后想到用Oracle的全局临时表的方式将数据抽取过来。

这里也有一个小插曲,就是有50多个表都是有lob字段的。

想写一个循环利用动态SQL来创建global temporary table,并且每次创建之前删除掉改全局临时表。

v_sql := '
create global temporary table table1
ON COMMIT PRESERVE ROWS as
select * from ' || v_table_name;
execute immediate v_sql; v_sql := 'insert into table1 ' || '
select * from ' || v_table_name || '@to_168_bi';
execute immediate v_sql;
v_sql := 'insert into ' || v_table_name || '
select * from table1';
execute immediate v_sql; commit;

这样创建的临时表默认是 COMMIT delete ROWS 的。

发现数据没有抽取过来,初步怀疑是动态执行SQL的时候自动提交了,这里有些没有想清楚。

之后创建全局临时表的时候加上了ON COMMIT PRESERVE ROWS。

数据是抽过来了,但是drop的时候会报错:ORA-14452: 试图创建, 变更或删除正在使用的临时表中的索引

declare
v_table_name varchar2(32);
v_sql varchar2(2000);
v_cnt number; cursor cur is
select t.TABLE_NAME
from user_tables t
where t.TABLE_NAME
in (select st.table_name
from user_tab_columns st
where st.DATA_TYPE in ('CLOB', 'BLOB'))
order by t.TABLE_NAME; begin for i in cur loop
v_table_name := i.table_name;
v_sql := 'truncate table ' || v_table_name;
execute immediate v_sql; select count(1) into v_cnt from user_tables t
where t.TABLE_NAME=upper('table1'); if v_cnt >0 then
execute immediate 'drop table table1';
end if; v_sql := 'create global temporary table table1
ON COMMIT PRESERVE ROWS
as' || '
select * from ' || v_table_name ||'@to_168_bi';
execute immediate v_sql; v_sql := 'insert into ' || v_table_name || '
select * from table1';
execute immediate v_sql;
commit;
end loop; exception
when others then
dbms_output.put_line(v_table_name || ':' || sqlcode || ':' || sqlerrm); end get_data_from168;

之后测试了一下,

SQL> create global temporary table table1 as select * from employees;

Table created.

SQL> drop table table1;

Table dropped.

SQL> create global temporary table table1 on commit preserve rows as select * from employees;

Table created.

SQL> drop table table1;
drop table table1
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already
in use

实验证明创建glob temporary table 的时候如果添加了on commit preserve rows在session没有退出的情况下是没发drop的。

之后这样写在SQLplus 中执行却没什么问题,plsql developer 的test procedure的方式是多session?

declare
v_table_name varchar2(32);
v_sql varchar2(2000);
v_cnt number; cursor cur is
select t.TABLE_NAME
from user_tables t
where t.TABLE_NAME
in (select st.table_name
from user_tab_columns st
where st.DATA_TYPE in ('CLOB', 'BLOB'))
order by t.TABLE_NAME; begin for i in cur loop
v_table_name := i.table_name;
v_sql := 'truncate table ' || v_table_name;
execute immediate v_sql; select count(1) into v_cnt from user_tables t
where t.TABLE_NAME=upper('table1'); if v_cnt >0 then
execute immediate 'drop table table1';
end if; /* v_sql := 'create global temporary table table1
ON COMMIT PRESERVE ROWS
as' || '
select * from ' || v_table_name ||'@to_168_bi';
execute immediate v_sql;*/ v_sql := 'create global temporary table table1
as' || '
select * from ' || v_table_name;
execute immediate v_sql; execute immediate ('insert into table1 select * from '||v_table_name||'@to_168_bi'); v_sql := 'insert into ' || v_table_name || '
select * from table1';
execute immediate v_sql;
commit;
end loop; exception
when others then
dbms_output.put_line(v_table_name || ':' || sqlcode || ':' || sqlerrm); end get_data_from168;

后来想想,如果用Kettle的话会更方便,结果用Kettle测试了一下,Kettle对于lob字段处理的也非常好。

之后Kettle会自动生成每个表对应的转换。

测试运行也没什么问题,非常方便。

一次Oracle数据迁移的更多相关文章

  1. Oracle数据迁移至HBase操作记录

    Oracle数据迁移至HBase操作记录 @(HBase) 近期需要把Oracle数据库中的十几张表T级别的数据迁移至HBase中,过程中遇到了许多苦难和疑惑,在此记录一下希望能帮到一些有同样需求的兄 ...

  2. Oracle数据迁移expdp/impdp

    Oracle数据迁移expdp/impdp目的:指导项目侧自行进行简单的数据泵迁移工作. 本文实验环境:Oracle 11.2.0.4,利用数据库自带的scott示例用户进行试验测试. 1.首先需要创 ...

  3. Oracle数据迁移至MySQL

    ORACLE DB: 11.2.0.3.0 MYSQL DB: 5.5.14 因项目需求,需要将ORACLE生产中数据迁移至MYSQL数据库中作为初始数据,方法有如下几种: 1.ORACLE OGG ...

  4. Oracle数据迁移笔记-Rownum与序列的自增长的组合用法技巧

    Rownum与序列的自增长的组合用法技巧 根据序列自增长的步长规律,结合表行记录Rownum值的规则批量生成表的行记录主键的用法技巧 案例如下: CREATE OR REPLACE PROCEDURE ...

  5. oracle数据迁移之Exp和Expdp导出数据的性能对比与优化

    https://wangbinbin0326.github.io/2017/03/31/oracle%E6%95%B0%E6%8D%AE%E8%BF%81%E7%A7%BB%E4%B9%8BExp%E ...

  6. Oracle数据迁移后由列的直方图统计信息引起的执行计划异常

    (一)问题背景 在使用impdp进行数据导入的时候,往往在导入表和索引的统计信息的时候,速度非常慢,因此我在使用impdp进行导入时,会使用exclude=table_statistics排除表的统计 ...

  7. 【Oracle 数据迁移】环境oracle 11gR2,exp无法导出空表的表结构【转载】

    今天做数据迁移,但是发现有些空表无法exp,后来找到问题所在. [原文]:http://www.cnblogs.com/wenlong/p/3684230.html 11GR2中有个新特性,当表无数据 ...

  8. Oracle数据迁移-系统数据合并笔记

    创建临时表:execute immediate 'sql'; 通过临时表和关联查询解决循环处理效率低下,大数据操作移植时时间太长的问题. 结构相同的系统数据库表移植,案例如下: create or r ...

  9. oracle数据迁移

    通过这个文章演示一下Oracle的表空间迁移流程以及需要注意的诸多事项. 实验目标:将ora10g数据库实例上的表空间TBS_SEC_D迁移到secooler数据库实例上操作系统:Redhat 5.3 ...

  10. oracle 数据迁移之数据泵的基本使用

    oracle相同数据库下跨schema的表迁移—expdp/impdp 需求:将GUIDO用户下的表迁移到SCOTT用户下 select * from dba_role_privs where GRA ...

随机推荐

  1. [Effective C++ --012]复制对象时勿忘其每一个成分

    引言: 在深拷贝和浅拷贝的理解中,我们知道了“拷贝构造函数”一词,并且也了解了它的构成. A(const A& r); // 形式有多种,在这里只列出一个 因此,在值传递的应用场景里,我们可以 ...

  2. myql定义和查看语句

     创建数据库: create database IF NOT EXISTS MY_TEST default charset utf8  COLLATE utf8_general_ci; 查看SQL语句 ...

  3. Android ADB启动失败 ADB server out of date

    调试Android程序时总提示ADB未运行,转到命令行方式下启动ADB, adb kille-server停止ADB, 然后再运行adb start-server 随后提示: adb server i ...

  4. gdb显示内存命令用法简介

    http://blog.csdn.net/allenlinrui/article/details/5964046

  5. Tomcat服务器启动常见问题

    参考:http://www.cnblogs.com/xdp-gacl/p/3729033.html 学习web开发,需要先安装一台web服务器,然后再在web服务器中开发相应的web资源,供用户使用浏 ...

  6. css扁平化博客学习总结(四)content代码实现

    1.根据功能,把不同的部分写出来,方便扩展 <div class="content"><!-- 内容开始 --> <section class=&qu ...

  7. 编辑一个小的smarty类

    首先先建立两个文件夹,一个temp,存储编译前的文件,一个comp,存储编译后的文件,编译前的文件使用{$title}代替<?php echo $title; ?>,然后将前者编译成后者再 ...

  8. 【转】MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作

    [转]MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作 上一篇博文MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据, ...

  9. JAXB - Hello World

    We'll stick with the tradition and use a sort of "Hello World" XML document to illustrate ...

  10. java web 优化札记

    1.效果最明显最简单最省事的优化是SSD,一般优化效率3倍起,(未必对,但是说明很多瓶颈问题都是存储问题) 2.垂直扩容省了开发时间,短期来看是最快的,缺点是会消耗更多的资源,而且有瓶颈,另外如果应用 ...