对于无备份情况下的ORA-1578、ORA-8103、ORA-1410等逻辑/物理坏块问题,可以通过如下PL/SQL 构造ROWID的方式挽救绝大多数非坏块的数据, 一般分成 2种情况 有索引可以用来获取ROWID, 或者 没有索引、索引不可用,必须通过dbms_rowid.ROWID_CREATE来构造ROWID的方式。 对于有索引的情况,可以直接使用MOS上提供的脚本:
REM Create a new table based on the table that is producing errors with no rows: create table as select * from where 1=2; REM Create the table to keep track of ROWIDs pointing to affected rows: create table bad_rows (row_id rowid ,oracle_error_code number); set serveroutput on DECLARE TYPE RowIDTab IS TABLE OF ROWID INDEX BY BINARY_INTEGER; CURSOR c1 IS select /*+ index(tab1) */ rowid from tab1 where is NOT NULL; r RowIDTab; rows NATURAL := 20000; bad_rows number := 0 ; errors number; error_code number; myrowid rowid; BEGIN OPEN c1; LOOP FETCH c1 BULK COLLECT INTO r LIMIT rows; EXIT WHEN r.count=0; BEGIN FORALL i IN r.FIRST..r.LAST SAVE EXCEPTIONS insert into select /*+ ROWID(A) */ from A where rowid = r(i); EXCEPTION when OTHERS then BEGIN errors := SQL%BULK_EXCEPTIONS.COUNT; FOR err1 IN 1..errors LOOP error_code := SQL%BULK_EXCEPTIONS(err1).ERROR_CODE; if error_code in (1410, 8103, 1578) then myrowid := r(SQL%BULK_EXCEPTIONS(err1).ERROR_INDEX); bad_rows := bad_rows + 1; insert into bad_rows values(myrowid, error_code); else raise; end if; END LOOP; END; END; commit; END LOOP; commit; CLOSE c1; dbms_output.put_line('Total Bad Rows: '||bad_rows); END; /对于没有索引或者索引损坏的情况可以使用如下方法:
创建示例数据 create table maclean_tab1 (t1 int,t2 date default sysdate) tablespace users partition by range(t1) (partition p1 values less than (10000), partition p2 values less than (20000), partition p3 values less than (30000), partition p4 values less than (40000), partition p5 values less than (50000), partition p6 values less than (60000), partition p7 values less than (70000), partition p8 values less than (80000), partition p9 values less than (90000), partition p10 values less than (100000), partition p11 values less than (110000), partition p12 values less than (120000), partition p13 values less than (130000), partition p14 values less than (140000), partition p15 values less than (150000), partition p16 values less than (160000)) ; insert into maclean_tab1(t1) select rownum from dual connect by level<160000; commit; SQL> select count(*) from maclean_tab1;
本文转自maclean_007 51CTO博客,原文链接:http://blog.51cto.com/maclean/1278533