首页 » ORACLE 9i-23ai » 如何在oracle PL/SQL loop中捕获异常Exception继续?

如何在oracle PL/SQL loop中捕获异常Exception继续?

在Oracle PL/SQL中,在循环中捕获异常并继续执行可以通过使用异常块实现。如循环kill session 可能会遇到session marked killed报错中断,或flush shared pool 中的sql时,因为有部分sql keep, 遍历时会遇到ora-6596 错误 ,下面是一个简单的示例,演示了如何在PL/SQL循环中捕获异常并继续执行:

BEGIN
  FOR i IN 1..10 LOOP
    BEGIN
      -- 在这里放置你的代码,可能会引发异常
      NULL; -- 举例:这里是你的实际代码
    EXCEPTION
      WHEN others THEN
        -- 在这里处理或记录异常
        dbms_output.put_line('Exception occurred, but continuing loop iteration: ' || SQLERRM);
    END;
  END LOOP;
END;

在上述示例中,FOR 循环内部包含一个 BEGIN ... END 块,该块包含实际的逻辑代码。如果任何一个循环迭代中的代码引发异常,异常将被捕获并在 EXCEPTION 块中处理。WHEN others 表示捕获所有类型的异常,但是最好在实际情况中根据需要更具体地捕获异常。

如kill tx blocker session

declare
blockcount number;
sqlreport varchar(3000);
sqloutput varchar(5000);
v_rec varchar(3000);
v_sql varchar(2000);

cursor blk_curs is select s.USERNAME BUSER,s.SID BSID,s.SERIAL# BSERIAL,s.STATUS BSTAT,s.program,s.LAST_CALL_ET BLAST  from dba_waiters w,v$session s where w.lock_type='Transaction'  and W.HOLDING_SESSION=s.SID
 and s.username not in ('SYSTEM','DBSNMP','RMAN') 
 and s.last_call_et>=60;
begin
    DBMS_OUTPUT.put_line('Checking for blocking sessions on this database');
    DBMS_OUTPUT.put_line('-----------------------------------------------');
    select count(*) into blockcount from  dba_blockers;
        IF blockcount > 0 THEN
            DBMS_OUTPUT.put_line('Found blocking sessions -> Fetching report for the same');
            DBMS_OUTPUT.put_line('-------------------------------------------------------');
            for v_rec in blk_curs LOOP
                dbms_output.put_line('Blocker: ('||v_rec.BUSER ||' program'||v_rec.program||' ('||v_rec.BSID||','||v_rec.BSERIAL||') is Currently '||v_rec.BSTAT||' for last '||v_rec.BLAST||' Sec '||')');
            end loop;
            DBMS_OUTPUT.put_line('-');
            DBMS_OUTPUT.put_line('-');
            DBMS_OUTPUT.put_line('Further details on blocking sessions -> includes kill script of blocking session');
            DBMS_OUTPUT.put_line('--------------------------------------------------------------------------------');
            for v_rec in blk_curs LOOP
                BEGIN
                v_sql:='alter system kill session '''
                            || v_rec.BSID
                            || ', '
                            || v_rec.BSERIAL
                            || '''immediate';
                DBMS_OUTPUT.put_line(v_sql);	
                -- execution kill
                execute immediate v_sql;
                	EXCEPTION
                         WHEN OTHERS
                         THEN
                            DBMS_OUTPUT.PUT_LINE (SQLCODE);
                END;
            end loop;
            DBMS_OUTPUT.put_line('-');
            DBMS_OUTPUT.put_line('-');
        ELSE
            DBMS_OUTPUT.put_line('-');
            DBMS_OUTPUT.put_line('-');
            DBMS_OUTPUT.put_line('Hurrey !!! No blocking sessions found');
            DBMS_OUTPUT.put_line('-');
            DBMS_OUTPUT.put_line('-');
        END IF;
    
    EXCEPTION
       WHEN OTHERS
       THEN
          DBMS_OUTPUT.PUT_LINE (SQLCODE);
    	  
END;

flush shared pool SQL

DECLARE
   curstr   VARCHAR2 (300);
BEGIN
   FOR cur
      IN (SELECT address, hash_value
            FROM v$sqlarea
           WHERE     executions=1             
           AND LAST_LOAD_TIME < SYSDATE - 1/24
  )
   LOOP
      BEGIN
        curstr := 'begin sys.dbms_shared_pool.purge(:b1,''c'',65); end;';
	  
        --     DBMS_OUTPUT.put_line ('exec sys.dbms_shared_pool.purge('':b1,:b2'',''c'',65)');
        EXECUTE IMMEDIATE (curstr) USING cur.address || ',' || cur.hash_value;
	  
        EXCEPTION
        WHEN OTHERS
        THEN
           DBMS_OUTPUT.PUT_LINE (SQLCODE);
      END;
   END LOOP;
END;
/

通过在异常处理程序中记录异常信息或采取适当的措施,你可以保证即使在循环中出现异常,程序也能继续进行下一次迭代。

请注意,对于很多情况来说,考虑在处理后继续执行之前,确保已解决异常引发的问题是非常重要的。

打赏

,

对不起,这篇文章暂时关闭评论。