Xóa dữ liệu không chỉ là một chức năng, nó là cả một nghệ thuật luôn! Quan trọng là phải xóa đúng cái cần xóa, đừng lỡ tay xóa nhầm (dữ liệu bị xóa nhầm có thể ám ảnh bạn trong những cơn ác mộng đấy). Hôm nay tụi mình sẽ học cách làm việc này cho chuẩn và an toàn nhé!
Xóa dữ liệu là quá trình loại bỏ một hoặc nhiều dòng khỏi bảng, những dòng này không còn phù hợp với logic nghiệp vụ hoặc yêu cầu của hệ thống nữa. Ví dụ, bạn cần xóa thông tin về các sinh viên đã tốt nghiệp hoặc, ừm, vi phạm nội quy trường nặng quá. Hoặc đơn giản là bạn cần dọn dẹp bảng để chỉ giữ lại thông tin mới nhất thôi.
Việc xóa dữ liệu thường dùng trong các trường hợp sau:
- Xóa thông tin về user không còn hoạt động nữa.
- Dọn dẹp bảng khỏi các bản ghi tạm thời.
- Xóa dữ liệu bị trùng lặp.
- Xóa các bản ghi cũ theo logic nghiệp vụ nhất định.
Cú pháp lệnh DELETE
Để xóa dữ liệu, tụi mình dùng lệnh DELETE. Đây là cú pháp cơ bản:
DELETE FROM bảng
WHERE điều_kiện;
Các thành phần chính:
DELETE FROM— cụm từ khóa để chỉ định là sẽ xóa dòng khỏi bảng.- bảng — tên bảng mà bạn muốn xóa dữ liệu.
WHERE điều_kiện— điều kiện lọc các dòng cần xóa. Ở đây bạn có thể dùng bất kỳ toán tử so sánh, toán tử logic (AND,OR,NOT) và thậm chí là subquery luôn.
Ví dụ: giả sử tụi mình có bảng students, và muốn xóa sinh viên có ID = 5:
DELETE FROM students
WHERE id = 5;
Lệnh này sẽ xóa dòng trong bảng students mà id của sinh viên (cột id) bằng 5.
Lưu ý: nếu bạn quên ghi điều kiện WHERE, PostgreSQL sẽ xóa tất cả các dòng trong bảng luôn. Lỗi này có thể rất thảm họa, nhất là khi bạn đang làm trên hệ thống production.
Xóa tất cả các dòng trong bảng
Nếu bạn muốn xóa hết mọi dòng trong bảng, có thể viết lệnh không có điều kiện WHERE. Ví dụ:
DELETE FROM students;
Lệnh này sẽ xóa tất cả bản ghi trong bảng students. Tuy nhiên, cấu trúc bảng vẫn còn nguyên — chỉ là bảng sẽ trống thôi.
Phương án khác: TRUNCATE
Để xóa hết mọi dòng trong bảng, bạn cũng có thể dùng lệnh TRUNCATE. Nó chạy nhanh hơn DELETE vì không ghi lại từng dòng bị xóa vào transaction log. Ví dụ:
TRUNCATE TABLE students;
Khác biệt giữa DELETE và TRUNCATE:
DELETEghi lại từng thao tác xóa vào transaction log, nên có thể rollback nếu cần.TRUNCATEkhông hỗ trợ điều kiện (WHERE) và không ghi lại từng dòng bị xóa, nên nhanh hơn nhưng kém linh hoạt hơn.
Nếu bạn chỉ muốn làm sạch bảng, TRUNCATE là lựa chọn ngon. Nhưng nếu cần xóa một phần dữ liệu hoặc muốn có khả năng rollback, nên dùng DELETE.
Xóa dữ liệu với điều kiện phức tạp
Điều kiện trong DELETE không chỉ đơn giản mà còn có thể phức tạp, dùng toán tử logic (AND, OR, NOT) hoặc subquery luôn. Xem ví dụ nhé.
Ví dụ 1: Xóa nhiều bản ghi Xóa tất cả sinh viên có tuổi lớn hơn 30 và không đi học trong 3 tháng gần đây:
DELETE FROM students
WHERE age > 30 AND last_attendance_date < (CURRENT_DATE - INTERVAL '3 months');
Lệnh này chỉ xóa những sinh viên thỏa mãn cả hai điều kiện cùng lúc.
Ví dụ 2: Xóa bằng subquery
Giả sử tụi mình có bảng failed_students, lưu id của các sinh viên bị đuổi học vì học kém. Cần xóa họ khỏi bảng chính students:
DELETE FROM students
WHERE id IN (SELECT student_id FROM failed_students);
Ở đây subquery trả về tất cả id sinh viên trong bảng failed_students, và lệnh DELETE sẽ xóa các dòng tương ứng trong bảng students.
Gợi ý
Trước khi xóa gì đó, hãy viết một lệnh SELECT để xem trước dữ liệu bạn định xóa. Sau đó chỉ cần thay SELECT bằng DELETE, nó sẽ xóa đúng những dòng vừa hiển thị.
Ví dụ thực tế
Giả sử sinh viên có ID = 7 quyết định chuyển trường. Xóa hết thông tin về bạn ấy khỏi bảng:
DELETE FROM students
WHERE id = 7;
Kiểm tra lại bảng sau khi chạy lệnh để chắc chắn bản ghi đã bị xóa:
SELECT * FROM students WHERE id = 7;
Nếu không còn bản ghi nào có ID = 7, việc xóa đã thành công.
Cảnh báo và lỗi thường gặp
Quên phần WHERE
Một trong những lỗi phổ biến nhất khi dùng DELETE là quên phần WHERE. Điều này sẽ xóa tất cả các dòng trong bảng, có thể gây thảm họa thực sự. Luôn kiểm tra kỹ lệnh trước khi chạy nhé.
Ví dụ về tình huống quên điều kiện:
DELETE FROM students;
-- Lỗi! Đã xóa hết sinh viên.
Để tránh lỗi này, nên test điều kiện WHERE bằng lệnh SELECT trước khi chạy DELETE. Ví dụ:
SELECT * FROM students WHERE id = 5;
Nếu kết quả đúng ý, bạn có thể tự tin chạy DELETE rồi.
Xóa dữ liệu liên quan
Nếu bảng có khóa ngoại (FOREIGN KEY), khi xóa dữ liệu có thể gặp lỗi. Điều này xảy ra nếu dòng bị xóa có liên kết với các bản ghi khác. Ví dụ, nếu sinh viên đã đăng ký môn học trong bảng enrollments, PostgreSQL sẽ không cho bạn xóa khỏi bảng students.
Để xử lý, bạn có thể:
- Dùng xóa cascade
ON DELETE CASCADEkhi tạo khóa ngoại. - Xóa thủ công các bản ghi liên quan trước khi xóa bản ghi chính.
Ví dụ xóa thủ công dữ liệu liên quan:
-- xóa thông tin về sinh viên 5 khỏi bảng enrollments trước
DELETE FROM enrollments
WHERE student_id = 5;
-- sau đó xóa sinh viên 5
DELETE FROM students
WHERE id = 5;
Xóa với transaction
Với các thao tác xóa quan trọng, nên dùng transaction. Như vậy bạn có thể rollback nếu có lỗi.
Ví dụ xóa trong transaction:
BEGIN;
DELETE FROM students
WHERE id = 42;
-- Kiểm tra kết quả
SELECT * FROM students WHERE id = 42;
-- Nếu ok thì commit
COMMIT;
-- Nếu không thì rollback
-- ROLLBACK;
Chi tiết về transaction sẽ có ở các bài sau nha :P
GO TO FULL VERSION