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:
- Tạo ra thông báo giải thích điều gì đã xảy ra không đúng.
- Dừng thực thi code khi gặp lỗi nghiêm trọng.
- 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_violationhoặcdivision_by_zero.OTHERS— dùng để xử lý mọi lỗi chưa được liệt kê trong các blockWHEN.
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
- 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. - Dùng
RAISEđể debug. Đừng bao giờ bỏ qua lỗi không xử lý. - Đừ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!
GO TO FULL VERSION