自定义异常的声明语法格式如下:

    1. exception_name EXCEPTION;

    自定义异常也可以使用PRAGMA EXCEPTION_INIT``(exception_name, error_code)``;

    语句跟现有的错误码关联起来,其中,error_code是 OceanBase 已有的错误码编号。

    示例:声明和处理自定义异常

    1. delimiter /
    2. CREATE OR REPLACE PROCEDURE sp_test_user_exception(p_w_id IN ware.w_id%TYPE )
    3. AS
    4. TYPE TYPE_REFCURSOR IS REF CURSOR ;
    5. ref_cursor TYPE_REFCURSOR;
    6. ware_name ware.w_name%TYPE;
    7. READ_NOTHING EXCEPTION;
    8. PRAGMA EXCEPTION_INIT(READ_NOTHING,-4026);
    9. BEGIN
    10. OPEN ref_cursor FOR SELECT w_name FROM ware WHERE ( w_id = p_w_id AND p_w_id IS NOT NULL ) OR (p_w_id IS NULL );
    11. FETCH ref_cursor INTO ware_name ;
    12. IF ref_cursor%NOTFOUND THEN
    13. RAISE READ_NOTHING;
    14. ELSE
    15. dbms_output.put_line('Fetch a ware name : ' || ware_name || '.');
    16. END IF;
    17. CLOSE ref_cursor;
    18. EXCEPTION
    19. WHEN CURSOR_ALREADY_OPEN THEN
    20. dbms_output.put_line('Handle a CURSOR_ALREADY_OPEN exception. ');
    21. WHEN NO_DATA_FOUND THEN
    22. dbms_output.put_line('Handle a NO_DATA_FOUND exception. ');
    23. WHEN TOO_MANY_ROWS THEN
    24. dbms_output.put_line('Handle a TOO_MANY_ROWS exception. ');
    25. END;
    26. /
    27. delimiter ;
    28. obclient> set serveroutput on;
    29. Query OK, 0 rows affected (0.00 sec)
    30. obclient> call sp_test_user_exception(2);
    31. Query OK, 0 rows affected (0.05 sec)
    32. Fetch a ware name : L6xwRsbDk.
    33. obclient> call sp_test_user_exception(3);
    34. Query OK, 0 rows affected (0.00 sec)
    35. Handle a NO_DATA_FOUND exception.
    36. obclient>

    在这个示列中将一个自定义异常跟错误码 -4026 关联,实际上就是跟 OceanBase 预定义异常 NO_DATA_FOUND 进行关联。所以,在最后面的异常处理部分能被处理。语句 RAISE READ_NOTHING;也可以直接改为 RAISE NO_DATA_FOUND;,效果是一样的。

    另外一种用户自定义异常可以通过 RAISE_APPLICATION_ERROR 方法直接抛出,不能被异常处理逻辑捕获。RAISE_APPLICATION_ERROR 语法格式如下:

    1. RAISE_APPLICATION_ERROR( error_number, error_message )

    其中,error_number 是从 -20000 到 -20999 之间的整数,error_message提示相应的信息(少于2048字节)。示例如下:

    1. delimiter /
    2. CREATE OR REPLACE PROCEDURE sp_test_exception(p_w_id IN ware.w_id%TYPE )
    3. AS
    4. TYPE TYPE_REFCURSOR IS REF CURSOR ;
    5. ref_cursor TYPE_REFCURSOR;
    6. ware_name ware.w_name%TYPE;
    7. sum_ytd number(10,2) := -1;
    8. BEGIN
    9. IF p_w_id IS NULL THEN
    10. RAISE_APPLICATION_ERROR(-20000, 'Warehouse ID is NULL!');
    11. END IF;
    12. OPEN ref_cursor FOR SELECT w_name FROM ware WHERE w_id = p_w_id ;
    13. FETCH ref_cursor INTO ware_name ;
    14. IF ref_cursor%NOTFOUND THEN
    15. dbms_output.put_line('Fetch a ware name but ref cursor return NOTFOUND.');
    16. ELSE
    17. dbms_output.put_line('Fetch a ware name : ' || ware_name || '.');
    18. END IF;
    19. CLOSE ref_cursor;
    20. EXCEPTION
    21. WHEN CURSOR_ALREADY_OPEN THEN
    22. dbms_output.put_line('Handle a CURSOR_ALREADY_OPEN exception [' || sqlcode || ':' || sqlerrm || '] !');
    23. WHEN NO_DATA_FOUND THEN
    24. dbms_output.put_line('Handle a NO_DATA_FOUND exception [' || sqlcode || ':' || sqlerrm || '] !');
    25. WHEN TOO_MANY_ROWS THEN
    26. dbms_output.put_line('Handle a TOO_MANY_ROWS exception [' || sqlcode || ':' || sqlerrm || '] . ');
    27. WHEN OTHERS THEN
    28. dbms_output.put_line('Raise an unkown exception [' || sqlcode || ':' || sqlerrm || '] !');
    29. RAISE ;
    30. END;
    31. /
    32. delimiter ;
    33. obclient> call sp_test_exception(null);
    34. ERROR-20000: Warehouse ID is NULL!
    35. obclient>