Xử lý ngoại lệ trong Oracle PL/SQL (Ví dụ)
⚡ Tóm tắt thông minh
Xử lý ngoại lệ trong Oracle PL/SQL bắt các lỗi thời gian chạy khiến một khối lệnh không thể thực thi, cho phép công cụ chuyển quyền điều khiển đến phần EXCEPTION, nơi các trình xử lý được định nghĩa trước, do người dùng định nghĩa và các trình xử lý KHÁC sẽ phản hồi, báo cáo hoặc truyền lỗi một cách an toàn.

Xử lý ngoại lệ trong PL/SQL là gì?
Một ngoại lệ xảy ra khi công cụ PL/SQL gặp phải một lệnh mà nó không thể thực thi do lỗi phát sinh trong quá trình chạy. Những lỗi này không được phát hiện trong quá trình biên dịch và do đó chỉ có thể được xử lý trong quá trình chạy.
Ví dụ, nếu công cụ PL/SQL nhận được lệnh chia một số cho 0, nó sẽ báo lỗi dưới dạng một ngoại lệ. Ngoại lệ này chỉ được công cụ PL/SQL đưa ra trong quá trình thực thi.
Một ngoại lệ làm dừng chương trình và ngăn không cho nó tiếp tục thực thi, vì vậy để tránh tình trạng này, lỗi cần được bắt và xử lý riêng biệt. Quá trình này được gọi là xử lý ngoại lệ, trong đó lập trình viên xử lý lỗi có thể xảy ra trong quá trình chạy chương trình.
Cú pháp xử lý ngoại lệ
Các ngoại lệ được xử lý ở cấp độ khối. Khi một ngoại lệ xảy ra trong một khối, quyền điều khiển sẽ rời khỏi phần thực thi của khối đó, và ngoại lệ sau đó được xử lý trong phần xử lý ngoại lệ của khối. Sau khi ngoại lệ được xử lý, quyền điều khiển không thể quay lại phần thực thi của cùng khối đó.
Hình minh họa bên dưới cho thấy phần thực thi và phần xử lý ngoại lệ nằm trong cùng một khối PL/SQL:
Cú pháp dưới đây giải thích cách bắt và xử lý ngoại lệ.
BEGIN <execution block> . . EXCEPTION WHEN <exceptionl_name> THEN <Exception handling code for the “exception 1 _name’' > WHEN OTHERS THEN <Default exception handling code for all exceptions > END;
Giải thích cú pháp:
- Trong cú pháp trên, khối xử lý ngoại lệ chứa một loạt các điều kiện WHEN để xử lý các ngoại lệ.
- Mỗi điều kiện WHEN đều được theo sau bởi tên của một ngoại lệ dự kiến sẽ được ném ra trong quá trình thực thi.
- Khi một ngoại lệ được phát sinh trong quá trình thực thi, công cụ PL/SQL sẽ tìm kiếm ngoại lệ đó trong phần xử lý ngoại lệ, bắt đầu từ mệnh đề WHEN đầu tiên và di chuyển tuần tự.
- Nếu tìm thấy trình xử lý cho ngoại lệ được đưa ra, nó sẽ thực thi mã của trình xử lý đó.
- Nếu không có mệnh đề WHEN nào khớp với ngoại lệ được đưa ra, công cụ PL/SQL sẽ thực thi phần WHEN OTHERS, nếu có. Trình xử lý này áp dụng chung cho tất cả các ngoại lệ.
- Sau khi trình xử lý chạy xong, quyền điều khiển sẽ rời khỏi khối hiện tại.
- Chỉ có một trình xử lý ngoại lệ duy nhất được thực thi cho một khối mã tại thời điểm chạy. Sau khi trình xử lý đó chạy xong, hệ thống sẽ bỏ qua các trình xử lý còn lại và kết thúc khối mã hiện tại.
Lưu ý: Lệnh WHEN OTHERS luôn phải được đặt cuối cùng trong chuỗi lệnh. Bất kỳ trình xử lý nào được viết sau WHEN OTHERS sẽ không bao giờ chạy, bởi vì quyền điều khiển sẽ thoát khỏi khối lệnh ngay khi WHEN OTHERS đã được thực thi.
Các loại ngoại lệ
Có hai loại ngoại lệ trong PL / SQL.
- Ngoại lệ được xác định trước
- Các ngoại lệ do người dùng xác định
Ngoại lệ được xác định trước
Oracle đã định nghĩa trước một số ngoại lệ phổ biến. Mỗi ngoại lệ được định nghĩa trước đều có tên và mã lỗi duy nhất, và tất cả chúng đều được khai báo trong gói STANDARD. OracleTrong mã lập trình, bạn có thể sử dụng trực tiếp các tên ngoại lệ được định nghĩa trước này để xử lý các lỗi tương ứng. Nhiều trong số chúng ánh xạ trực tiếp đến các ngoại lệ thông thường. SQL Những lỗi bạn gặp phải mỗi ngày.
Dưới đây là một vài trường hợp ngoại lệ đã được định sẵn:
| Ngoại lệ | lỗi Code | Lý do ngoại lệ |
|---|---|---|
| ACCESS_INTO_NULL | ORA-06530 | Gán giá trị cho các thuộc tính của một đối tượng chưa được khởi tạo. |
| CASE_NOT_FOUND | ORA-06592 | Không có mệnh đề WHEN nào trong câu lệnh CASE được thỏa mãn và không có mệnh đề ELSE nào được chỉ định. |
| BỘ SƯU TẬP_IS_NULL | ORA-06531 | Sử dụng các phương thức của tập hợp (ngoại trừ EXISTS) hoặc truy cập các thuộc tính của tập hợp trên một tập hợp chưa được khởi tạo. |
| CURSOR_ALREADY_OPEN | ORA-06511 | Đang cố gắng mở một con trỏ đã mở |
| DUP_VAL_ON_INDEX | ORA-00001 | Lưu trữ giá trị trùng lặp trong cột cơ sở dữ liệu bị ràng buộc bởi chỉ mục duy nhất. |
| INVALID_CURSOR | ORA-01001 | Các thao tác con trỏ bất hợp pháp, chẳng hạn như đóng một con trỏ chưa được mở. |
| INVALID_NUMBER | ORA-01722 | Việc chuyển đổi ký tự thành số đã thất bại do ký tự số không hợp lệ. |
| KHÔNG TÌM THẤY DỮ LIỆU NÀO | ORA-01403 | Câu lệnh SELECT chứa mệnh đề INTO sẽ không truy xuất bất kỳ hàng nào. |
| ROW_MISMATCH | ORA-06504 | Kiểu dữ liệu của biến con trỏ không tương thích với kiểu dữ liệu trả về thực tế của con trỏ. |
| ĐĂNG KÝ_BEYOND_COUNT | ORA-06533 | Tham chiếu đến một bộ sưu tập bằng số chỉ mục lớn hơn kích thước của bộ sưu tập. |
| SUBSCRIPT_OUTSIDE_LIMIT | ORA-06532 | Tham chiếu đến một bộ sưu tập bằng số chỉ mục nằm ngoài phạm vi hợp lệ (ví dụ: -1) |
| TOO_MANY_ROWS | ORA-01422 | Câu lệnh SELECT với mệnh đề INTO trả về nhiều hơn một hàng. |
| VALUE_ERROR | ORA-06502 | Lỗi tính toán hoặc lỗi liên quan đến giới hạn kích thước (ví dụ: gán giá trị lớn hơn kích thước biến). |
| ZERO_DIVIDE | ORA-01476 | Chia một số cho số không |
Ngoại lệ do người dùng xác định
Ngoài các ngoại lệ được định nghĩa trước ở trên, lập trình viên có thể tạo ra các ngoại lệ tùy chỉnh và xử lý chúng. Chúng được tạo ra ở cấp độ chương trình con trong phần khai báo và chỉ hiển thị bên trong chương trình con đó. Một ngoại lệ được định nghĩa trong phần khai báo gói là một ngoại lệ công khai và hiển thị ở bất cứ nơi nào có thể truy cập gói đó.
Cú pháp: Ở cấp độ chương trình con
DECLARE <exception_name> EXCEPTION; BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> END;
- Trong cú pháp trên, biến 'exception_name' được định nghĩa là kiểu EXCEPTION.
- Sau đó, nó có thể được sử dụng theo cùng một cách như một ngoại lệ được định nghĩa trước.
Cú pháp: Ở cấp độ đặc tả gói
CREATE PACKAGE <package_name> IS <exception_name> EXCEPTION; . . END <package_name>;
- Trong cú pháp trên, biến 'exception_name' được định nghĩa là kiểu EXCEPTION trong phần mô tả gói của .
- Nó có thể được sử dụng trên toàn bộ cơ sở dữ liệu ở bất cứ nơi nào có thể gọi gói 'package_name'.
PL/SQL Tăng ngoại lệ
Tất cả các ngoại lệ được định nghĩa trước đều được tự động ném ra mỗi khi lỗi tương ứng xảy ra. Tuy nhiên, các ngoại lệ do người dùng định nghĩa phải được ném ra một cách rõ ràng bằng cách sử dụng từ khóa RAISE. RAISE có thể được sử dụng theo các cách được hiển thị bên dưới.
Nếu RAISE được sử dụng riêng lẻ bên trong một hàm xử lý, nó sẽ truyền ngoại lệ đã được ném ra đến khối cha. Nó chỉ có thể được sử dụng bên trong một khối xử lý ngoại lệ, như được hiển thị bên dưới.
Ảnh chụp màn hình bên dưới cho thấy RAISE được sử dụng riêng lẻ để tái tạo một ngoại lệ cho khối lệnh bao quanh:
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> RAISE; END;
Giải thích cú pháp:
- Trong cú pháp trên, từ khóa RAISE được sử dụng bên trong khối xử lý ngoại lệ.
- Mỗi khi chương trình gặp phải ngoại lệ 'exception_name', ngoại lệ đó sẽ được xử lý và chương trình sẽ hoàn tất bình thường.
- Từ khóa RAISE trong hàm xử lý sau đó sẽ truyền cùng một ngoại lệ đó đến chương trình cha.
Lưu ý: Khi ném một ngoại lệ vào khối cha, ngoại lệ được ném ra cũng phải hiển thị trong khối cha; nếu không thì... Oracle ném một lỗi.
Bạn cũng có thể sử dụng từ khóa RAISE theo sau là tên ngoại lệ để tạo ra ngoại lệ do người dùng định nghĩa hoặc ngoại lệ được định sẵn đó. Hình thức này có thể được sử dụng cả trong phần thực thi và phần xử lý ngoại lệ.
Ảnh chụp màn hình bên dưới hiển thị lệnh RAISE theo sau là tên ngoại lệ để tạo ra một ngoại lệ cụ thể:
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> RAISE <exception_name> EXCEPTION WHEN <exception_name> THEN <Handler> END;
Giải thích cú pháp:
- Trong cú pháp trên, từ khóa RAISE được sử dụng trong phần thực thi, theo sau là ngoại lệ 'exception_name'.
- Điều này gây ra ngoại lệ cụ thể đó trong quá trình thực thi, và sau đó cần phải được xử lý hoặc báo cáo thêm.
Ví dụ 1: Trong ví dụ này, chúng ta sẽ thấy:
- Cách khai báo ngoại lệ
- Làm thế nào để tạo ra ngoại lệ đã khai báo?
- Làm thế nào để truyền nó vào khối chính
Ảnh chụp màn hình bên dưới hiển thị toàn bộ khối lệnh khai báo sample_exception, ném ngoại lệ đó bên trong một khối lệnh lồng nhau và truyền nó đến khối lệnh chính:
Ảnh chụp màn hình sau đây cho thấy ví dụ tương tự được tiếp tục, trong đó khối chính cuối cùng bắt được ngoại lệ lan truyền:
DECLARE Sample_exception EXCEPTION; PROCEDURE nested_block IS BEGIN Dbms_output.put_line('Inside nested block'); Dbms_output.put_line('Raising sample_exception from nested block'); RAISE sample_exception; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line ('Exception captured in nested block. Raising to main block'); RAISE; END; BEGIN Dbms_output.put_line('Inside main block'); Dbms_output.put_line('Calling nested block'); Nested_block; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line ('Exception captured in main block'); END; /
Code Giải thích:
- Code dòng 2: Khai báo biến 'sample_exception' thuộc kiểu EXCEPTION.
- Code dòng 3: Khai báo thủ tục nested_block.
- Code dòng 6: In ra câu lệnh “Bên trong khối lồng nhau”.
- Code dòng 7: In ra thông báo “Raising sample_exception from nested block”.
- Code dòng 8: Đưa ra ngoại lệ bằng cách sử dụng 'RAISE sample_Exception'.
- Code dòng 10: Trình xử lý ngoại lệ cho ngoại lệ sample_exception trong khối lồng nhau.
- Code dòng 11: In ra thông báo “Ngoại lệ được bắt trong khối lồng nhau. Đưa lỗi về khối chính”.
- Code dòng 12: Đưa ngoại lệ lên khối chính (truyền nó đi).
- Code dòng 15: In ra câu lệnh “Bên trong khối chính”.
- Code dòng 16: In câu lệnh “Gọi khối lồng nhau”.
- Code dòng 17: Gọi thủ tục nested_block.
- Code dòng 19: Trình xử lý ngoại lệ cho sample_Exception trong khối chính.
- Code dòng 20: In ra thông báo “Ngoại lệ được bắt trong khối chính”.
Những điểm quan trọng cần lưu ý trong Ngoại lệ
- Trong một hàm, ngoại lệ luôn phải trả về một giá trị hoặc gây ra ngoại lệ tiếp theo; nếu không thì ngược lại. Oracle Gây ra lỗi 'Hàm trả về mà không có giá trị' khi chạy.
- Báo cáo kiểm soát giao dịch có thể được phát hành bên trong khối xử lý ngoại lệ.
- SQLERRM và SQLCODE là các hàm tích hợp sẵn, lần lượt trả về thông báo lỗi và mã lỗi.
- Nếu ngoại lệ không được xử lý, theo mặc định tất cả các giao dịch đang hoạt động trong phiên đó sẽ bị hoàn tác.
- RAISE_APPLICATION_ERROR (- , Có thể sử dụng ) thay cho RAISE để báo lỗi với mã và thông báo tùy chỉnh. Mã lỗi phải nằm trong khoảng từ -20000 đến -20999.





