FOR LOOP和EXECUTE IMMEDIATE的异常处理

时间:2016-03-28 04:58:14

标签: oracle plsql

我的任务是打印表格的总列数。然后,对于特定ID,仅打印那些列'具有值的名称(如果列包含该特定ID的null,则跳过它)。我在FOR LOOP中的代码中使用EXECUTE IMMEDIATE。如果EXECUTE IMMEDIATE在列中找不到数据,那么它会抛出我可以处理的no_data_exception,但是我不能在该异常之后继续我的循环。

DECLARE
    COL_TOTAL_NUM NUMBER;
    COL_NAME VARCHAR2(500);
    COL_VAL VARCHAR2(500);
BEGIN
    SELECT COUNT(*) INTO COL_TOTAL_NUM FROM user_tab_cols WHERE TABLE_NAME='PAY_SLIP_FEB_16';
    DBMS_OUTPUT.PUT_LINE('TOTAL COLUMN NUMBER = '||COL_TOTAL_NUM);
    FOR A IN 1..COL_TOTAL_NUM LOOP
      SAVEPOINT S1;
      SELECT COLUMN_NAME INTO COL_NAME FROM user_tab_cols WHERE TABLE_NAME='PAY_SLIP_FEB_16'
                                                  AND COLUMN_ID=A;
      EXECUTE IMMEDIATE 'SELECT '||COL_NAME||' FROM PAY_SLIP_FEB_16 WHERE EMP_ID=''FMINF83057'' AND '||COL_NAME||' IS NOT NULL' INTO COL_NAME;
      DBMS_OUTPUT.PUT_LINE(COL_NAME||' -> '||COL_VAL);
    END LOOP;
    EXCEPTION
      WHEN no_data_found THEN
        DBMS_OUTPUT.PUT_LINE('ERROR');
        ROLLBACK TO SAVEPOINT S1;
END;  

我的输出是:

TOTAL COLUMN NUMBER = 117
EMP_ID -> FMINF83057
MONTH -> 2
YEAR -> 2016
NAME ->   Mr.Md.Mohiduzzaman
DESIGNATION -> Professor
DEPARTMENT -> Institute of Nutrition and Food Sciences
GRADE -> 2
BASIC_PAY -> 73720
HOUSE_RENT_ALLOWANCE -> 19750
MEDICAL_ALLOWANCE -> 700
ERROR  

for循环在这里停止。该错误后如何继续?

1 个答案:

答案 0 :(得分:0)

遇到错误时,您只需要使用CONTINUE语句。它可以从Oracle 11g开始提供。但是你需要在里面循环。我将你的异常部分移动到循环中,并将其包含在一个块中:

DECLARE
    COL_TOTAL_NUM NUMBER;
    COL_NAME VARCHAR2(500);
    COL_VAL VARCHAR2(500);
BEGIN
    SELECT COUNT(*) INTO COL_TOTAL_NUM FROM user_tab_cols WHERE TABLE_NAME='PAY_SLIP_FEB_16';
    DBMS_OUTPUT.PUT_LINE('TOTAL COLUMN NUMBER = '||COL_TOTAL_NUM);
    FOR A IN 1..COL_TOTAL_NUM LOOP
    BEGIN
      SAVEPOINT S1;
      SELECT COLUMN_NAME INTO COL_NAME FROM user_tab_cols WHERE TABLE_NAME='PAY_SLIP_FEB_16'
                                              AND COLUMN_ID=A;
      EXECUTE IMMEDIATE 'SELECT '||COL_NAME||' FROM PAY_SLIP_FEB_16 WHERE EMP_ID=''FMINF83057'' AND '||COL_NAME||' IS NOT NULL' INTO COL_NAME;
      DBMS_OUTPUT.PUT_LINE(COL_NAME||' -> '||COL_VAL);
    EXCEPTION
      WHEN no_data_found THEN
        DBMS_OUTPUT.PUT_LINE('ERROR');
        CONTINUE;                         --move to the next iteration of the loop
    END;
    END LOOP;
END; 

该语句告诉编译器跳过循环的当前迭代并跳转到下一个循环。它对于日志记录特别有用。