转载

ora-01502 索引或这类索引的分区处于不可用状态"的解决方案


如题,在ORACLE中自动新增删除分区之后,会报出ora-01502的错误。


首先,问题的原因是在于进行表结构修改后,索引失效。问题解决有如下几个方式:


1、手动查询重建


(1)先查询失效索引,语句为:


      select index_name ,status  from user_indexes where Status = 'UNUSABLE' ;

(2)重建索引,语句为: 


  1.   
  2. alter index  xxx rebuild;

手动操作有个快捷的方式,可以将上面的步骤合成为一个查询语句:   


 select 'alter index ' || index_name || ' rebuild;' from user_indexes where Status = 'UNUSABLE' ;

这样直接复制查询出来的语句手动执行即可。


2、将上面的手动操作做成存储过程执行的“只能自动”


(1)创建重建索引的存储过程,语句如下:


  1. create or replace procedure p_rebuild_all_index
  2.    (tablespace_name in varchar2,--这里是表空间名,如果不改变表空间,可以传入null
  3.    only_unusable in boolean)    --是否仅对无效的索引操作
  4. as
  5.    sqlt varchar(200);
  6. begin
  7.     --只取非临时索引
  8.     for idx in (select index_name, tablespace_name, status from user_indexes where temporary = 'N'loop
  9.         --如果是如重建无效的索引,且当索引不是无效时,则跳过
  10.         if only_unusable = true and idx.status <> 'UNUSABLE' then
  11.            goto continue;
  12.         end if;
  13.         if (tablespace_name is null) or idx.status = 'UNUSABLE' then
  14.            --如果没有指定表空间,或索引无效,则在原表空间重建
  15.            sqlt := 'alter index ' || idx.index_name || ' rebuild ';
  16.         elsif upper(tablespace_name) <> idx.tablespace_name then
  17.            --如果指定的不同的表空间,则在指定表空间待建索引
  18.            sqlt := 'alter index ' || idx.index_name || ' rebuild tablespace ' || tablespace_name;
  19.         else
  20.            --如果表空间相同,则跳过
  21.            goto continue;
  22.         end if;
  23.         dbms_output.put_line(idx.index_name);
  24.         EXECUTE IMMEDIATE sqlt;
  25.         <<continue>>
  26.         null;
  27.      end loop;
  28. end;

(2) 创建执行重建的存储过程


  1. CREATE OR REPLACE PROCEDURE EXEC_REBUILD_PROC AS
  2.     v_err_num  NUMBER;  --ORA错误号
  3.    v_err_msg  VARCHAR2(100); --错误描述
  4. BEGIN
  5.  --10代表创建10天的分区,tablespace代表表空间名
  6.  p_rebuild_all_index(NULL,true);
  7.  COMMIT;
  8. EXCEPTION
  9.  WHEN OTHERS THEN
  10.   v_err_num := SQLCODE;
  11.   v_err_msg := SUBSTR(SQLERRM, 1, 100);
  12.   dbms_output.put_line('EXEC_REBUILD_PROC执行出现异常,错误码='|| v_err_num || '错误描述=' || v_err_msg);
  13. END EXEC_REBUILD_PROC;

如此即可。以上方式均已测试可用。


正文到此结束
本文目录