Xóa hàng loạt giữ lại một số bản ghi với NOT IN trong MySQL
Sử dụng DELETE ... WHERE column NOT IN (value1, value2, ...) để xóa tất cả hàng KHÔNG nằm trong danh sách giữ lại.
Cú pháp
DELETE FROM yourTableName
WHERE yourColumnName NOT IN ('keepValue1', 'keepValue2', 'keepValue3', ...);
Ví dụ: Giữ lại John, Mike, Carol
Tạo bảng:
mysql> CREATE TABLE deleteAllRowsWithCondition (
-> Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> Name VARCHAR(20)
-> );
Chèn 7 hàng:
mysql> INSERT INTO deleteAllRowsWithCondition(Name) VALUES
('Larry'), ('John'), ('Sam'), ('Mike'), ('Carol'), ('Bob'), ('David');
Dữ liệu ban đầu:
+----+-------+ | Id | Name | +----+-------+ | 1 | Larry | | 2 | John | | 3 | Sam | | 4 | Mike | | 5 | Carol | | 6 | Bob | | 7 | David | +----+-------+
Xóa tất cả KHÔNG phải John, Mike, Carol:
mysql> DELETE FROM deleteAllRowsWithCondition
WHERE Name NOT IN ('John', 'Mike', 'Carol');
Query OK, 4 rows affected (0.15 sec)
Kết quả (còn lại 3 hàng):
+----+-------+ | Id | Name | +----+-------+ | 2 | John | | 4 | Mike | | 5 | Carol | +----+-------+
Lưu ý quan trọng
- NULL trong NOT IN: Nếu cột có NULL,
NOT IN (..., NULL)luôn trả về UNKNOWN → không xóa hàng nào. Khắc phục:WHERE Name NOT IN ('John','Mike') AND Name IS NOT NULL - Subquery:
WHERE id NOT IN (SELECT id FROM keep_table) - Performance: Với danh sách lớn, dùng JOIN hoặc EXISTS tốt hơn
Cách an toàn hơn: NOT EXISTS
DELETE FROM deleteAllRowsWithCondition d
WHERE NOT EXISTS (
SELECT 1 FROM (SELECT 'John' AS n UNION SELECT 'Mike' UNION SELECT 'Carol') k
WHERE k.n = d.Name
);
Best Practice trước khi DELETE
SELECT * FROM table WHERE condition;- Xem trước hàng sẽ bị xóaSTART TRANSACTION;- Bọc trong transaction- Thực hiện DELETE
- Kiểm tra lại →
COMMIT;hoặcROLLBACK;