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.

  • ⚙️ Lỗi khi chạy chương trình: Một ngoại lệ phát sinh khi công cụ PL/SQL gặp phải một lệnh mà nó không thể thực thi, chẳng hạn như chia một số cho số không.
  • 🧱 Cấu trúc khối: Các trường hợp ngoại lệ được xử lý trong phần EXCEPTION bằng cách sử dụng mệnh đề WHEN, trong đó WHEN OTHERS luôn được đặt ở vị trí cuối cùng.
  • 📚 Các ngoại lệ được xác định trước: Oracle Đặt tên cho các lỗi thường gặp như NO_DATA_FOUND và ZERO_DIVIDE trong gói STANDARD, sẵn sàng để bắt trực tiếp.
  • 🛠️ Các ngoại lệ do người dùng định nghĩa: Lập trình viên tự khai báo các biến EXCEPTION và kích hoạt chúng một cách rõ ràng bằng từ khóa RAISE.
  • ⬆️ Sự lan truyền: Một ngoại lệ không được xử lý sẽ được truyền đến khối bao quanh và hàm RAISE sẽ gửi tín hiệu đó trở lại chương trình cha.
  • 🤖 Hỗ trợ AI: Các công cụ lập trình AI soạn thảo các khối EXCEPTION và gắn cờ các đường dẫn lỗi chưa được xử lý trong quá trình xem xét.

Xử lý ngoại lệ trong Oracle PL / SQL

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ấu trúc của một khối PL/SQL với phần thực thi và phần xử lý ngoại lệ.

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:

Truyền một ngoại lệ đến khối cha bằng lệnh RAISE đơn thuần.

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ể:

Tạo một ngoại lệ cụ thể có tên bằng cách sử dụng lệnh RAISE theo sau là tên của ngoại lệ.

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:

Ví dụ PL/SQL về việc khai báo và ném ra một ngoại lệ do người dùng định nghĩa trong một khối lồng nhau.

Ả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:

Kết quả hiển thị ngoại lệ được bắt trước tiên trong khối lồng nhau và sau đó trong khối chính.

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.

Câu Hỏi Thường Gặp

Lệnh PRAGMA EXCEPTION_INIT liên kết tên ngoại lệ do người dùng khai báo với một ngoại lệ cụ thể. Oracle Mã lỗi. Sau khi liên kết, bạn có thể bắt lỗi ORA đó theo tên trong mệnh đề WHEN thay vì sử dụng WHEN OTHERS và kiểm tra SQLCODE.

Hàm SQLCODE trả về mã lỗi dạng số của ngoại lệ hiện tại, trong khi hàm SQLERRM trả về thông báo lỗi dạng văn bản. Cả hai hàm đều được gọi bên trong trình xử lý ngoại lệ, thường là khối WHEN OTHERS, để ghi nhật ký hoặc hiển thị những gì đã xảy ra sai sót.

Tránh sử dụng WHEN OTHERS vì nó sẽ âm thầm bỏ qua mọi lỗi. Nếu không ghi nhật ký SQLCODE và SQLERRM hoặc không ném lại lỗi bằng RAISE, nó sẽ che giấu lỗi. Chỉ sử dụng nó để ghi nhật ký, dọn dẹp và sau đó truyền ngoại lệ.

Hàm RAISE_APPLICATION_ERROR chấp nhận mã lỗi nằm trong khoảng từ -20000 đến -20999 và thông báo lỗi tối đa 2048 byte. Hàm này dừng quá trình thực thi và trả về lỗi tùy chỉnh cho ứng dụng gọi, làm cho điều kiện do người dùng định nghĩa trông giống như một điều kiện gốc. Oracle lỗi.

Không nằm trong cùng một khối lệnh — một khi quyền điều khiển chuyển đến phần EXCEPTION, khối lệnh đó sẽ kết thúc. Để tiếp tục, hãy bao bọc câu lệnh có rủi ro trong một khối lệnh BEGIN…EXCEPTION…END bên trong; sau khi xử lý lỗi, khối lệnh bên ngoài sẽ tiếp tục thực thi.

Lỗi là bất kỳ vấn đề nào phát sinh trong quá trình thực thi hoặc biên dịch mã. Ngoại lệ là cơ chế thực thi PL/SQL thể hiện lỗi trong quá trình thực thi, chuyển quyền điều khiển đến phần EXCEPTION để chương trình có thể phản hồi thay vì kết thúc đột ngột.

Đúng vậy. Các trợ lý AI và trình đánh giá mã máy học sẽ soạn thảo các khối EXCEPTION, đề xuất các ngoại lệ được định nghĩa trước cần bắt và gắn cờ các đường dẫn mã thiếu trình xử lý. Tuy nhiên, nhà phát triển vẫn nên xác nhận logic và thông báo lỗi trước khi triển khai.

Trợ lý GitHub Chức năng tự động hoàn thành các mệnh đề WHEN, các lệnh gọi RAISE_APPLICATION_ERROR và toàn bộ khối EXCEPTION từ một đoạn chú thích ngắn mô tả mục đích. Nó giúp tăng tốc quá trình lập trình trình xử lý thường xuyên, mặc dù mã lỗi và thông báo được tạo ra cần được xem xét lại để đảm bảo tính chính xác.

Tóm tắt bài viết này với: