Cùng phân tích các lỗi phổ biến khi chèn dữ liệu mới vào bảng nhé.
Lỗi 1: Thử chèn NULL vào trường bắt buộc
PostgreSQL rất nghiêm ngặt trong việc đảm bảo các rule của database được tuân thủ. Xem ví dụ về các constraint có thể gây ra lỗi:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL, -- Tên không được phép là NULL
age INT
);
-- Lỗi: trường name là bắt buộc phải điền
INSERT INTO students (name, age) VALUES (NULL, 20);
Kết quả: lỗi null value in column "name" of relation "students" violates not-null constraint`.
Bạn cần chú ý dữ liệu mình thêm vào. Có thể cột này trước cho phép NULL, nhưng giờ nó là trường bắt buộc rồi.
Lỗi 2: Trùng lặp dữ liệu ở cột unique.
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY,
course_name TEXT UNIQUE -- Tên khóa học phải là duy nhất
);
-- Lần chèn đầu tiên thành công
INSERT INTO courses (course_name) VALUES ('SQL Basics');
-- Lần chèn thứ hai gây lỗi
INSERT INTO courses (course_name) VALUES ('SQL Basics');
Kết quả: lỗi duplicate key value violates unique constraint`.
Thường thì đây không phải lỗi của bạn đâu, mà là user lỡ tay làm lại thao tác thôi. Trường hợp này bạn không cần làm gì cả.
Lỗi 3: Vi phạm tính toàn vẹn tham chiếu.
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY,
student_id INT REFERENCES students(id), -- Phải có student với ID như vậy
course_id INT REFERENCES courses(course_id)
);
-- Lỗi: student với ID = 99 không tồn tại
INSERT INTO enrollments (student_id, course_id) VALUES (99, 1);
Kết quả: lỗi insert or update on table "enrollments" violates foreign key constraint`.
Lỗi này xuất hiện là tốt đấy. Không gì tệ hơn việc làm hỏng tính toàn vẹn của database. Có thể code thao tác với database bị lỗi, hoặc dữ liệu đã cũ. Dù sao thì database không cho phép phá vỡ tính toàn vẹn là rất tốt rồi.
Xử lý lỗi trong PostgreSQL
Ừ thì lỗi là chuyện thường. Nhưng quan trọng là không chỉ phát hiện mà còn biết cách xử lý nữa.
Transaction như một công cụ bảo vệ
Khi làm việc với dữ liệu, tụi mình hay dùng transaction để đảm bảo tính nhất quán. Nếu có lỗi, mình có thể rollback lại thay đổi.
Ví dụ: thêm dữ liệu vào hai bảng.
BEGIN; -- Bắt đầu transaction
-- Chèn dữ liệu vào bảng students
INSERT INTO students (name, age) VALUES ('Otto Lin', 21);
-- Chèn bản ghi vào bảng enrollments
-- Ở đây sẽ lỗi nếu không có course với ID=10
INSERT INTO enrollments (student_id, course_id) VALUES (1, 10);
-- Nếu mọi thứ ok
COMMIT;
-- Nếu có lỗi, "quay lại" thay đổi
ROLLBACK;
Nếu không có course_id = 10, việc chèn vào bảng students cũng sẽ bị hủy luôn.
Xử lý lỗi trong transaction
Trong PostgreSQL, bạn có thể dự đoán lỗi và xử lý ngay trong query bằng block EXCEPTION.
Ví dụ: thêm student và ghi danh vào khóa học. Nếu có lỗi, sẽ ghi log lỗi lại.
DO $$
BEGIN
-- Thử chèn dữ liệu
INSERT INTO students (name, age) VALUES ('Anna Song', 22);
INSERT INTO enrollments (student_id, course_id) VALUES (2, 999); -- Lỗi
-- Nếu thành công
RAISE NOTICE 'Ghi thành công!';
EXCEPTION
WHEN foreign_key_violation THEN
-- Xử lý lỗi khóa ngoại
RAISE WARNING 'Khóa học với course_id này không tồn tại.';
END $$;
Kiểm tra unique bằng ON CONFLICT
Bạn có thể chủ động tránh lỗi vi phạm UNIQUE bằng cách dùng ON CONFLICT. Nó cho phép bạn chỉ định cách xử lý khi có conflict.
Ví dụ: khi thử chèn khóa học trùng, sẽ bỏ qua thao tác chèn.
INSERT INTO courses (course_name)
VALUES ('SQL Basics')
ON CONFLICT (course_name) DO NOTHING; -- Bỏ qua dữ liệu trùng
Hoặc cập nhật dòng đã có:
INSERT INTO courses (course_name)
VALUES ('SQL Basics')
ON CONFLICT (course_name) DO UPDATE
SET course_name = EXCLUDED.course_name || ' (Updated)';
Mình sẽ nói kỹ hơn về ON CONFLICT ở level sau, khi học về bulk data load :P
Các lỗi phổ biến khi thao tác dữ liệu và cách phòng tránh
Bạn đã thấy, nguồn gốc lỗi chủ yếu là:
- Vi phạm constraint (
NOT NULL,UNIQUE,FOREIGN KEY). - Thiếu điều kiện trong query (
WHERE) khi update hoặc xóa dữ liệu. - Lỗi thứ tự thực hiện transaction.
Để tự bảo vệ mình:
- Dùng transaction và rollback
ROLLBACKcho các thao tác lớn. - Luôn kiểm tra dữ liệu trước khi chèn.
- Log lại lỗi để phân tích.
- Dùng
ON CONFLICTđể tránh ghi trùng lặp.
Giờ bạn đã có kiến thức để chiến đấu với lỗi rồi! Nhớ nhé: dev giỏi không phải là người không bao giờ sai, mà là người biết sửa lỗi của mình.
GO TO FULL VERSION