CodeGym /Các khóa học /SQL SELF /Xử lý lỗi: RAISE EXCEPTION

Xử lý lỗi: RAISE EXCEPTION

SQL SELF
Mức độ , Bài học
Có sẵn

Giả sử bạn đang viết một function tính điểm trung bình của sinh viên. Điều gì sẽ xảy ra nếu bạn thử chia cho 0 (ví dụ khi không có điểm nào)? Nếu bạn để code như vậy chạy ngoài thực tế — thì lỗi sẽ xuất hiện ngay lập tức. PL/pgSQL cung cấp cho bạn những công cụ mạnh mẽ để xử lý các lỗi như vậy, giúp code của bạn vững chắc, an toàn và dễ làm việc hơn.

Xử lý lỗi trong PL/pgSQL cho phép bạn:

  1. Tạo ra thông báo giải thích điều gì đã xảy ra không đúng.
  2. Dừng thực thi code khi gặp lỗi nghiêm trọng.
  3. Ghi log các vấn đề để phân tích sau này.

Các mức thông báo chính trong PL/pgSQL

PL/pgSQL hỗ trợ nhiều mức thông báo khác nhau, giúp dev dễ dàng chẩn đoán và sửa lỗi. Đây là các mức đó:

  • NOTICE: in ra thông báo thông tin. Thường dùng để debug.
  • WARNING: cảnh báo về vấn đề tiềm ẩn, nhưng không dừng chương trình.
  • EXCEPTION: lỗi nghiêm trọng, dừng chương trình (và trả quyền điều khiển về code gọi).

Các mức thông báo trong PL/pgSQL

Mức thông báo Mô tả
NOTICE Thông tin hoặc thông báo debug. Không ảnh hưởng đến thực thi
WARNING Cảnh báo về vấn đề có thể xảy ra. Như một gợi ý
EXCEPTION Lỗi nghiêm trọng, dừng chương trình

Cú pháp lệnh RAISE

Để tạo thông báo và xử lý lỗi, bạn dùng lệnh RAISE. Đây là cú pháp cơ bản:

RAISE <mức thông báo> 'nội dung thông báo' [, biến...];
  • <mức thông báo>NOTICE, WARNING, EXCEPTION.
  • 'nội dung thông báo' — mô tả vấn đề.
  • [biến...] — các giá trị bổ sung có thể truyền vào thông báo.

Ví dụ 1: dùng RAISE NOTICE

Đôi khi bạn cần biết chuyện gì đang xảy ra trong function. Ví dụ, để debug vòng lặp:

DO $$
BEGIN
    FOR i IN 1..5 LOOP
        RAISE NOTICE 'Giá trị hiện tại của i: %', i;
    END LOOP;
END
$$;

Kết quả: In ra console các dòng Giá trị hiện tại của i: 1, Giá trị hiện tại của i: 2... đến 5.

Ví dụ 2: dùng RAISE EXCEPTION

Giờ giả sử bạn viết function cần dừng lại và báo lỗi khi gặp điều kiện nào đó:

DO $$
BEGIN
    IF 1 = 1 THEN
        RAISE EXCEPTION 'Có gì đó không ổn!';
    END IF;
END
$$;

Kết quả: chương trình dừng lại, thông báo lỗi in ra console.

Làm việc với tham số trong RAISE

Dùng tham số, bạn có thể cá nhân hóa nội dung thông báo. Để làm vậy, dùng placeholder %:

Ví dụ 3: chèn biến vào RAISE

DO $$
DECLARE
    student_name TEXT := 'Ivan';
    average_score NUMERIC := NULL;
BEGIN
    IF average_score IS NULL THEN
        RAISE EXCEPTION 'Sinh viên % không có điểm trung bình!', student_name;
    END IF;
END
$$;

Kết quả: thông báo Sinh viên Ivan không có điểm trung bình!.

Như bạn thấy, % sẽ được thay bằng biến student_name, giúp thông báo dễ hiểu hơn.

Tạo lỗi tuỳ chỉnh

Lỗi không chỉ là sự cố bất ngờ! Đôi khi bạn cần tạo lỗi có chủ đích để bảo vệ code khỏi dữ liệu sai.

Ví dụ 4: kiểm tra giá trị đầu vào

Viết function kiểm tra giá trị số đầu vào và báo lỗi nếu nó âm:

CREATE OR REPLACE FUNCTION check_positive(value NUMERIC)
RETURNS TEXT AS $$
BEGIN
    IF value < 0 THEN
        RAISE EXCEPTION 'Số % là số âm!', value;
    END IF;
    RETURN 'Số hợp lệ.';
END;
$$ LANGUAGE plpgsql;

Giờ test function này:

SELECT check_positive(-5);

Kết quả: thông báo lỗi Số -5 là số âm!.

Nếu truyền giá trị dương:

SELECT check_positive(10);

Kết quả: Số hợp lệ.

Xử lý lỗi trong context

Biết tạo lỗi là tốt rồi. Nhưng còn tốt hơn nếu bạn biết xử lý lỗi tuỳ tình huống. Để làm vậy, dùng block BEGIN ... EXCEPTION.

Cấu trúc xử lý lỗi

BEGIN
    -- Code chính của bạn
EXCEPTION
    WHEN LOAI_LOI THEN
        -- Làm gì khi gặp lỗi này
    WHEN LOI_KHAC THEN
        -- Xử lý lỗi khác
    WHEN OTHERS THEN
        -- Xử lý các lỗi còn lại
END;

Giải thích các thành phần:

  • EXCEPTION — từ khoá bắt đầu block xử lý lỗi.
  • WHEN — chỉ định loại lỗi cụ thể cần xử lý, ví dụ unique_violation hoặc division_by_zero.
  • OTHERS — dùng để xử lý mọi lỗi chưa được liệt kê trong các block WHEN.

Ví dụ 5: xử lý chia cho 0

Minh hoạ xử lý lỗi bằng ví dụ function chia số đơn giản:

CREATE OR REPLACE FUNCTION safe_divide(a NUMERIC, b NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
    -- Thử thực hiện phép chia
    RETURN a / b;
EXCEPTION
    WHEN division_by_zero THEN
        RAISE WARNING 'Thử chia cho 0. Trả về NULL.';
        RETURN NULL;
END;
$$ LANGUAGE plpgsql;

Test function:

SELECT safe_divide(10, 2);  -- Kết quả mong đợi: 5
SELECT safe_divide(10, 0);  -- Kết quả mong đợi: NULL và cảnh báo trên console

Lỗi phổ biến khi dùng RAISE

Bỏ quên mức thông báo. Nếu bạn quên chỉ định mức, PostgreSQL sẽ báo lỗi.

Sai:

RAISE 'Thông báo không có mức';

Đúng:

RAISE NOTICE 'Thông báo với mức NOTICE';

Tham số sai. Nếu dùng %, nhớ truyền đủ số biến cần thiết.

Sai:

RAISE NOTICE 'Ví dụ với tham số %';

Đúng:

RAISE NOTICE 'Ví dụ với tham số %', 'giá trị';

Lạm dụng. Dùng RAISE EXCEPTION quá nhiều có thể làm gián đoạn các thao tác quan trọng. Hãy dùng hợp lý.

Mẹo hữu ích

  1. Cẩn thận với block WHEN OTHERS. Nếu có thể, hãy chỉ rõ lỗi cụ thể để tránh bắt nhầm lỗi cần xử lý khác.
  2. Dùng RAISE để debug. Đừng bao giờ bỏ qua lỗi không xử lý.
  3. Đừng quên hiệu năng. Xử lý lỗi có thể tốn tài nguyên, nhất là trong thủ tục lớn.

Nếu bạn làm đúng, thủ tục của bạn sẽ cực kỳ vững chắc và có thể sống sót qua cả những sự cố bất ngờ nhất. PM chắc chắn sẽ rất tự hào về bạn!

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION