我想请教一下,,怎么在存储过程里面判断多个DB_LINK的有效性?是这样的,我需要在系统里面抽取多个省份的数据, 必须为每个省份的建立一个DB_LINK,,,但是现在发现如果某个省份的DB_LINK出了问题, 程序就死掉了, 不会再往下走了. 以致影响了其他省份的抽取,所以我想在程序运行之前先写个程序验证配置表里面的DB_LINK的有效性, 有效的设为Y, 无效的设为N, 抽取程序只读取配置为Y的省份进行抽取.程序这样:      -- 先将所有的都失效
      update bicode.h_etl_pro_config h set h.v_valid='N';
      
      <<check1>> 
      -- 找出省公司对应的 用户名 DBLINK
      for pro_item in v_pro_cur loop
        v_check := 0;
        
        v_sql :='select 1 from dual@'|| pro_item.etl_db_link;
        execute immediate v_sql into v_check;          if v_check = 1 then 
           update bicode.h_etl_pro_config h set h.v_valid='Y'
           where h.pro_unit_code = pro_item.pro_unit_code;
           
           commit;
           
        end if;       end loop check1;
      
      --exception when others then goto check1;但是问题仍然是一样, 只要中间有某个无效的DBLINK出现, 整个程序就跳出来了, 接下来的那些就不检查了.exception 更加烦人. 不能不处理, 也不能加在FOR里面, 也不能用GOTO.
不能像JAVA的TRY CATCH那样,捕捉到了不处理,直接进行下一次的循环..

解决方案 »

  1.   

    在loop里循环处理异常,
    when others then
       null;
    对每条数据(即每个DBLINK)进行异常判断。若出现异常,不作为。继续检查。
      

  2.   

    但是exception不能写在LOOP里面啊!!!!PL/SQL报错
      

  3.   

    错误:PLS-00103: 出现符号 "EXCEPTION"在需要下列之一时:
            begin case declare
              end exit for goto if loop mod null pragma raise return select
              update while with <an identifier>
              <a double-quoted delimited-identifier> <a bind variable> <<
              close current delete fetch lock insert open rollback
              savepoint set sql execute commit forall merge pipe
    行:176
    文本:exception when others then null;
      

  4.   

           -- 找出省公司对应的 用户名 DBLINK
          for pro_item in v_pro_cur loop
            v_check := 0;
            
            v_sql :='select 1 from dual@'|| pro_item.etl_db_link;
            execute immediate v_sql into v_check;          if v_check = 1 then 
               update bicode.h_etl_pro_config h set h.v_valid='Y'
               where h.pro_unit_code = pro_item.pro_unit_code;
               
               commit;
               
            end if; 
            
            exception when others then null;        
          end loop check1;
      

  5.   

    用ORACLE自带的虚拟表@连接名就行了
      

  6.   

    给你个参考
    LOOP里必须写在begin ... end块里。SQL> create or replace procedure test
      2  IS
      3     v_areaid   area.areaid%TYPE;
      4
      5  begin
      6    FOR i IN 1..10 LOOP
      7       BEGIN
      8       SELECT areaid INTO v_areaid FROM area;
      9          EXCEPTION
     10             WHEN no_data_found THEN
     11                NULL;
     12       END;
     13    NULL;
     14    END LOOP;
     15  end ;
     16  /过程已创建。SQL> show error
    没有错误。
    SQL>
      

  7.   

     /*
         检查配置表里面的 DB_LINK 的有效性, 避免因为某个省的连接失败影响到其他省的抽取
        */
        procedure P_CHECK_DBLINK
        is
          -- 省公司的信息配置表
          cursor v_pro_cur is
          select * from bicode.h_etl_pro_config p
          order by p.date_base_name;
          
          v_sql   varchar2(500);
          v_check number :=0;   
               
        begin
          
          -- 先将所有的都失效
          update bicode.h_etl_pro_config h set h.v_valid='N';
          
          -- 找出省公司对应的 用户名 DBLINK
          for pro_item in v_pro_cur loop
             begin
              v_check := 0;
              
              v_sql :='select 1 from dual@'|| pro_item.etl_db_link;
              execute immediate v_sql into v_check;            if v_check = 1 then 
                 update bicode.h_etl_pro_config h set h.v_valid='Y'
                 where h.pro_unit_code = pro_item.pro_unit_code;
                 
                 commit;
                 
              end if;
               
            end;  
            exception when others then null;        
          end loop;
          
        end P_CHECK_DBLINK;
    晕,,,,为什么我的还是报错的?
      

  8.   

    咩哈哈....问题解决了!!!!!!!!!原来是我9楼那里的END写错位置了
    多谢suiziguo!!!!!!!!!!!!!!!!分全给你了
      

  9.   

    袄,不好意思,误会了。execute immediate v_sql into v_check; 
    上面这句可能触发异常,所以你要它发生异常时,程序继续运行,必须单独对其异常进行捕捉和处理。
    也就是说,要想做到子程序遇到异常继续,必须针对每一可能发生异常的单独的语句进行处理,而不是整个块。
    PL/SQL里就是这么麻烦,但这样也保持了事务完整性,从而保持数据一致性。
      

  10.   

    一个存储过程可以有多个异常块,只要在需要捕捉异常的时候
    增加begin ... exception...end就行了-- 先将所有的都失效 
    UPDATE bicode.h_etl_pro_config h SET h.v_valid = 'N';
    < < check1 >>
    -- 找出省公司对应的 用户名 DBLINK 
    FOR pro_item IN v_pro_cur LOOP
      v_sql := 'select 1 from dual@' || pro_item.etl_db_link;
      BEGIN
        EXECUTE IMMEDIATE v_sql
          INTO v_check;
        UPDATE bicode.h_etl_pro_config h
           SET h.v_valid = 'Y'
         WHERE h.pro_unit_code = pro_item.pro_unit_code;
        COMMIT;
      EXCEPTION
        WHEN OTHERS THEN
          NULL;
      END;
    END LOOP check1;