zoukankan      html  css  js  c++  java
  • 不同类型的数据跨表空间迁移的解决办法

    http://blog.csdn.net/passion_wang/article/details/6541369

    Oracle10g数据跨表空间迁移

    因某些开发人员由于对oracle数据库理解的不够深入,往往在建表的时候指定了当前用户非默认的表空间,这样就导致了在exp及imp等操作时候问题很多,因此需要将这些表及相关的数据迁移回当前用户的默认表空间里.Oracle10g数据数据库提供了一个Move命令可以把这样的数据对象进行跨表空间的迁移,也可以对含有BLOB、CLOB这样的二进制大字段的表进行move。但是Move命令不支持含Long型字段的数据表,针对这种情况,我们还可以使用copy命令来进行数据迁移,后面会提到,在此不详细说明。

    首先我们需要查出表空间名及相关信息
     select username,default_tablespace from dba_users where default_tablespace not in ('SYSAUX','SYSTEM','USERS');
    USERNAME                       DEFAULT_TABLESPACE
    ------------------------------ ------------------------------
    YDMM                           YDMM
    YDSK                           YDSK

     
    查询不同表空间的所有者及包含的数据对象
    select distinct owner  from dba_extents where tablespace_name='YDMM'; 
    OWNER 
    ---------
    YDMM     
    YDSK

    select distinct owner  from dba_extents where tablespace_name='YDSK'; 
    OWNER 
    ---------
    YDSK    

    从上面我们可以发现YDMM表空间还存放了YDSK用户的数据,接下来我们就来找出YDSK用户在YDMM表空间存在的数据对象,并将YDSK用户下的所有数据对象进行迁移到它对应的默认表空间YDSK里面去
     select owner,segment_name,partition_name,segment_type from dba_segments where tablespace_name='YDMM' and owner='YDSK';

    一般经常碰到的segment_type主要有TABLE,INDEX,TABLE PARTITION,INDEX PARTITION,LOBSEGMENT,LOBINDEX,LOB PARTITION等,下面我们就针对这些类型的数据段进行迁移
    --移动表T1到YDSK表空间里
    alter table T1 move tablespace YDSK;
    --移动T1表的索引idx_t1到YDSK表空间里
    alter index idx_t1 rebuild tablespace YDSK;
    --移动含有BLOB、CLOB的字段的表T2到YDSK表空间
    alter table T2 move tablespace YDSK lob(BLOB1,BLOB2) store as (tablespace  YDSK); /其中BLOB1,BLOB2是表T2中包含的blob字段,CLOB类似,
    移动BLOB、CLOB的字段语法
    --alter table table_name move [tablespace tbs_name] lob(lob_field1,lob_field2) store as (tablespace new_tbs_name);
    --如果LOB字段在分区表中,则增加partition关键字,如
    --alter table table_name move [partition partname] [tablespace tbs_name] lob(field) store as (tablespace new_tbs_name);

    当然,如果存在很多数据对象,我们可以通过构建SQL脚本的方式来进行迁移
    根据上面所列的数据段类型,构造数据对象跨表空间的move命令语句如下。
     set heading off;
     set echo off;
     set feedback off;
     set termout on;
     spool /home/oracle/move_table.sql;
     --移动表
    select distinct 'alter table YDSK.'|| segment_name || ' move tablespace YDSK;' from dba_extents where segment_type='TABLE' and tablespace_name='YDMM' and owner='YDSK';
     --移动索引
    select distinct 'alter index YDSK.'|| segment_name || ' rebuild tablespace YDSK;' from dba_extents where segment_type='INDEX' and tablespace_name='YDMM' and owner='YDSK';       
     --如果有分区表则需要移动分区表和分区表索引
     --移动分区表
    select distinct 'alter table YDSK.'|| segment_name || ' move partition '|| partition_name || ' tablespace YDSK;' from dba_extents where segment_type='TABLE PARTITION' and tablespace_name='YDMM' and owner='YDSK';
     --移动分区索引
    select distinct 'alter index YDSK.'|| segment_name || ' rebuild partition '|| partition_name || ' tablespace YDSK;' from dba_extents where segment_type='INDEX PARTITION' and tablespace_name='YDMM' and owner='YDSK';

    spool off;
    以sys/system身份登录数据库,就可以执行执行move_table.sql来进行数据的迁移了。

    前面提到了Move命令不支持含Long型字段的数据表,那么我们该如何对这样的表进行迁移了?其实很简单,就是用一个copy命令,下面我们来看下copy命令的用法与优点:
    COPY命令语法如下:
    COPY FROM user/password@dbname1 TO user/password@dbname2 CREATE/APPEND/INSERT/REPLACE TABLE_NAME (COLUMN_NAME, ……) USING SELECT * from table_name;
    简单地来描述一下上面语法中各子句的含义:
    FROM和TO语句:分别描述从哪个数据库COPY到哪个数据库,FROM或TO指向当前数据库时,可以忽略,但不能同时忽略FROM和TO。
    CREATE/APPEND/INSERT/REPLACE:COPY命令的四个选项,功能分别为创建表并插入数据/在已经存在的表的记录后面插入新数据/在空表中插入数据/删除表然后重建新表并插入新数据。
    TABLE_NAME (COLUMN_NAME, ……):复制后的表名和列名,如果列名列表省略的话,则会根据后面查询语句来确定列的名称。
    USING SELECT * from table_name:将该表查询的结果按照指定方法写入到前面的表中。

    COPY命令的的几个主要优点:
    1、支持LONG类型:由于CREATE TABLE AS和INSERT INTO SELECT都不支持LONG类型。这就导致了对LONG类型数据的处理十分麻烦,而使用存储过程的方法相对比较麻烦,利用EXP和IMP则有很多的限制条件。相对来说使用COPY是最简单快速的方法。
    2、不需要建立数据库链,只要本地的TNSNAMES.ORA中配置了远端数据库就可以直接访问。操作方便快捷。而且也支持本数据库到本数据库的COPY。
    3、语法灵活,支持目标表名列名与查询语句中不相符,而且还有多种数据处理方式。

    下面我们将做一个简单的例子来进行copy的具体操作。(T3是含有long型字段的表)
    创建一个含有long型字段的表T3
    SQL> CREATE TABLE T3 (ID NUMBER, DEFAULT_VALUE LONG);
    通过create table的方式进行复制
    SQL> CREATE TABLE T AS SELECT * FROM T3;
    CREATE TABLE T AS SELECT * FROM T3
    *
    ERROR 位于第 1 行:
    ORA-00997: 非法使用 LONG 数据类型

    通过insert into的方式进行复制
    SQL> CREATE TABLE T (ID NUMBER, DEFAULT_VALUE LONG);
    SQL> INSERT INTO T SELECT ID, DATA_DEFAULT FROM T3;
    INSERT INTO T SELECT ID, DATA_DEFAULT FROM T3
    *
    ERROR 位于第 1 行:
    ORA-00997: 非法使用 LONG 数据类型
    从上面看,使用常用的表复制方式的不行的,下面我们来使用copy命令进行复制
    SQL> DROP TABLE T;
    表已丢弃。
    SQL> COPY FROM YDMM/YDMM@ORCL TO YDSK/YDSKK@ORCL CREATE T USING SELECT * FROM T3;
    数组读取/结合的大小为15。(数组大小为15)
    将在完成时提交。(提交的复本为 0)
    最长为80。(长度为80)
    表T已创建。
    0行选自YDMM@ORCL
    0行被插入T。
    0行已提交至T(位于YDSK@ORCL)。

    其中每次读取数据数组大小有SET的ARRAYSIZE参数决定。每次提交的数据量由SET的COPYCOMMIT参数控制。COPY是否进行类型检查由SET的COPYTYPECHECK参数控制。COPY执行时LONG类型截取长度由SET的LONG参数控制。如果不希望LONG类型被截断,则保证LONG的值超过表中LONG类型的最长值。
    SQL> SET ARRAYSIZE 1000
    SQL> SET COPYCOMMIT 1000
    SQL> SET COPYTYPECHECK OFF
    SQL> SET LONG 100000
    SQL> COPY FROM YDMM/YDMM@ORCL TO YDSK/YDSKK@ORCL CREATE T USING SELECT * FROM T3;
    数组读取/结合的大小为1000。(数组大小为1000)
    将在每1000个数组结合之后提交。(提交的复本为1000)
    最长为100000。(长度为100000)
    0行选自YDMM@ORCL
    0行被插入T。
    0行已提交至T(位于YDSK@ORCL)。

    在使用COPY命令时,尽量只对用户自己的表进行操作。如果需要对其他用户下的表执行REPLACE操作时,仅仅拥有这个表的INSERT、DELETE权限是没有任何作用的,必须拥有CREATE ANY TABLE、DROP ANY TABLE和INSERT ANY TABLE系统权限。

  • 相关阅读:
    Androidの多线程之多线程用法大集合(未整理)
    Androidの多线程之更新ui(Thread+Handler+Message)
    构建之法阅读笔记1
    文件与流
    公文流转系统一
    JAVA web课堂测试1
    10.21动手动脑
    Android学习02
    Android学习01
    Android学习03
  • 原文地址:https://www.cnblogs.com/lteal/p/3816920.html
Copyright © 2011-2022 走看看