PL/SQL - Lỗi ngoại lệ: Hướng dẫn cho người mới bắt đầu

Xin chào các bạn tương lai của PL/SQL! Hôm nay, chúng ta sẽ cùng nhau khám phá thế giới fascininating của các lỗi ngoại lệ trong PL/SQL. Đừng lo lắng nếu bạn mới bắt đầu học lập trình - tôi sẽ hướng dẫn bạn từng bước qua chủ đề này, giống như tôi đã làm cho hàng trăm học sinh trong những năm dạy học của mình. Vậy, hãy lấy một tách cà phê (hoặc trà, nếu đó là sở thích của bạn), và cùng nhau bắt đầu hành trình thú vị này nhé!

PL/SQL - Exceptions

Lỗi ngoại lệ là gì?

Trước khi chúng ta đi sâu vào chi tiết, hãy hiểu về lỗi ngoại lệ là gì. Hãy tưởng tượng bạn đang nướng bánh (theo dõi tôi nhé, tôi promise rằng điều này liên quan đến lập trình). Bạn làm theo công thức từng bước, nhưng đột nhiên, bạn nhận ra rằng bạn đã hết trứng! Tình huống không mong muốn này tương tự như một lỗi ngoại lệ trong lập trình.

Trong PL/SQL, lỗi ngoại lệ là những sự kiện không mong muốn làm gián đoạn luồng chương trình bình thường. Chúng có thể là các lỗi như việc thử chia cho zero hoặc cố gắng chèn một giá trị trùng lặp vào một cột duy nhất. Thay vì để những vấn đề này làm crash chương trình của chúng ta, chúng ta có thể "xử lý" chúng một cách nhẹ nhàng - giống như cách bạn có thể sử dụng một chất thay thế cho trứng trong ví dụ nướng bánh của chúng ta.

Cú pháp cho việc xử lý lỗi ngoại lệ

Bây giờ, hãy xem cách chúng ta thực sự xử lý những lỗi ngoại lệ này trong PL/SQL. Cấu trúc cơ bản trông như thế này:

BEGIN
-- Mã bình thường của bạn ở đây
EXCEPTION
WHEN exception_name1 THEN
-- Xử lý lỗi 1
WHEN exception_name2 THEN
-- Xử lý lỗi 2
WHEN OTHERS THEN
-- Xử lý tất cả các lỗi khác
END;

Hãy phân tích điều này:

  1. Chúng ta viết mã bình thường của mình trong khối BEGIN.
  2. Nếu một lỗi ngoại lệ xảy ra, chương trình nhảy đến khối EXCEPTION.
  3. Chúng ta có thể xử lý các lỗi cụ thể bằng cách sử dụng các câu lệnh WHEN.
  4. Câu lệnh WHEN OTHERS bắt tất cả các lỗi mà chúng ta chưa xử lý cụ thể.

Dưới đây là một ví dụ đơn giản:

DECLARE
v_result NUMBER;
BEGIN
v_result := 10 / 0;  -- Điều này sẽ gây ra lỗi chia cho zero
DBMS_OUTPUT.PUT_LINE('Kết quả: ' || v_result);
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('Lỗi: Không thể chia cho zero!');
END;

Trong ví dụ này, chúng ta đang cố gắng chia 10 cho 0, điều này là toán học không thể. Thay vì crash, chương trình của chúng ta bắt lỗi ZERO_DIVIDE và hiển thị một thông báo lỗi thân thiện.

Khai báo lỗi

Đôi khi, chúng ta muốn tạo ra các lỗi ngoại lệ riêng của mình khi một số điều kiện được thỏa mãn. Chúng ta có thể làm điều này bằng cách sử dụng câu lệnh RAISE. Điều này giống như làm trọng tài trong một trận bóng đá - bạn thấy một lỗi, bạn thổi còi!

Dưới đây là cách nó hoạt động:

DECLARE
v_age NUMBER := 15;
BEGIN
IF v_age < 18 THEN
RAISE_APPLICATION_ERROR(-20001, 'Phải đủ 18 tuổi hoặc hơn');
END IF;
DBMS_OUTPUT.PUT_LINE('Chào mừng đến với câu lạc bộ!');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Lỗi: ' || SQLERRM);
END;

Trong ví dụ này, chúng ta đang kiểm tra xem ai đủ tuổi để vào câu lạc bộ. Nếu họ dưới 18 tuổi, chúng ta gây ra một lỗi ngoại lệ với một thông báo lỗi tùy chỉnh. Câu lệnh WHEN OTHERS bắt lỗi này và hiển thị thông báo lỗi.

Lỗi ngoại lệ do người dùng định nghĩa

Mặc dù PL/SQL cung cấp nhiều lỗi ngoại lệ đã định nghĩa sẵn cho các tình huống lỗi phổ biến, đôi khi chúng ta cần tạo ra lỗi của riêng mình. Điều này giống như tạo ra một quy tắc mới trong trò chơi của chúng ta. Dưới đây là cách chúng ta có thể làm điều đó:

DECLARE
e_invalid_name EXCEPTION;
v_name VARCHAR2(50) := 'J0hn';
BEGIN
IF NOT REGEXP_LIKE(v_name, '^[A-Za-z]+$') THEN
RAISE e_invalid_name;
END IF;
DBMS_OUTPUT.PUT_LINE('Tên hợp lệ: ' || v_name);
EXCEPTION
WHEN e_invalid_name THEN
DBMS_OUTPUT.PUT_LINE('Lỗi: Tên chỉ nên chứa chữ cái');
END;

Trong ví dụ này, chúng ta đã tạo một lỗi tùy chỉnh e_invalid_name. Chúng ta gây ra lỗi này nếu tên chứa bất kỳ thứ gì khác ngoài chữ cái. Điều này cho phép chúng ta xử lý tình huống cụ thể này theo cách có ý nghĩa cho chương trình của chúng ta.

Lỗi ngoại lệ đã định nghĩa sẵn

PL/SQL cung cấp một bộ lỗi ngoại lệ đã định nghĩa sẵn cho các tình huống lỗi phổ biến. Điều này giống như có một bộ cấp cứu sẵn sàng cho các chấn thương phổ biến. Dưới đây là một số lỗi ngoại lệ thường được sử dụng:

Tên Lỗi Mô tả
NO_DATA_FOUND Được gây ra khi một câu lệnh SELECT INTO không trả về bất kỳ hàng nào
TOO_MANY_ROWS Được gây ra khi một câu lệnh SELECT INTO trả về nhiều hơn một hàng
ZERO_DIVIDE Được gây ra khi cố gắng chia cho zero
DUP_VAL_ON_INDEX Được gây ra khi cố gắng chèn một giá trị trùng lặp vào một chỉ mục duy nhất
VALUE_ERROR Được gây ra khi có lỗi toán học, chuyển đổi, cắt bớt hoặc vi phạm giới hạn kích thước

Hãy xem một ví dụ sử dụng lỗi ngoại lệ đã định nghĩa sẵn:

DECLARE
v_emp_name VARCHAR2(50);
BEGIN
SELECT first_name INTO v_emp_name
FROM employees
WHERE employee_id = 1000;  -- Giả sử ID này không tồn tại

DBMS_OUTPUT.PUT_LINE('Tên nhân viên: ' || v_emp_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Lỗi: Không tìm thấy nhân viên với ID đó');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Lỗi: Tìm thấy nhiều hơn một nhân viên');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Đã xảy ra lỗi không mong muốn: ' || SQLERRM);
END;

Trong ví dụ này, chúng ta đang cố gắng lấy tên của một nhân viên. Nếu không có nhân viên nào được tìm thấy, chúng ta bắt lỗi NO_DATA_FOUND. Nếu có nhiều hơn một nhân viên được tìm thấy, chúng ta bắt lỗi TOO_MANY_ROWS. Bất kỳ lỗi không mong muốn nào khác sẽ được bắt bởi câu lệnh WHEN OTHERS.

Và thế là xong, các bạn! Chúng ta đã bao gồm các khái niệm cơ bản về xử lý lỗi ngoại lệ trong PL/SQL. Nhớ rằng, xử lý lỗi ngoại lệ giống như việc đeo dây an toàn - nó có thể看起来 không cần thiết khi mọi thứ diễn ra suôn sẻ, nhưng nó có thể cứu bạn khỏi rất nhiều rắc rối khi mọi thứ出错. Thực hành các khái niệm này, thử nghiệm với các tình huống khác nhau, và sớm bạn sẽ xử lý lỗi ngoại lệ như một chuyên gia. Chúc các bạn may mắn và hy vọng các chương trình của bạn luôn xử lý nhẹ nhàng các tình huống không mong muốn!

Credits: Image by storyset