MySQL không cho phép sửa đổi (UPDATE/DELETE) một bảng mà đồng thời SELECT từ bảng đó trong subquery (derived table). Lỗi: ERROR 1093 (HY000): You can't specify target table for update in FROM clause.
Ví dụ gây lỗi
DELETE FROM DemoTable1597 WHERE Marks = (SELECT MIN(Marks) FROM DemoTable1597);
Giải pháp: Bọc subquery thêm 1 lớp (derived table)
MySQL cho phép nếu subquery được wrap trong một derived table khác:
DELETE FROM DemoTable1597
WHERE Marks = (
SELECT lowestMarks FROM (
SELECT MIN(Marks) AS lowestMarks FROM DemoTable1597
) AS deleteRecord
) LIMIT 1;
Ví dụ minh họa
Tạo bảng và chèn dữ liệu:
CREATE TABLE DemoTable1597 (Marks INT); INSERT INTO DemoTable1597 VALUES (45), (59), (43), (85), (89);
Xóa giá trị nhỏ nhất (43):
DELETE FROM DemoTable1597
WHERE Marks = (
SELECT lowestMarks FROM (
SELECT MIN(Marks) AS lowestMarks FROM DemoTable1597
) AS deleteRecord
) LIMIT 1;
Kết quả
| Marks (còn lại) |
|---|
| 45 |
| 59 |
| 85 |
| 89 |
Giải thích
- Subquery trong ngoặc vuông
(SELECT MIN(Marks) ...)tạo derived table tạm thời. - Outer subquery
SELECT lowestMarks FROM (...) AS deleteRecord"materializes" kết quả → MySQL cho phép UPDATE/DELETE bảng gốc. LIMIT 1: Chỉ xóa 1 hàng nếu có nhiều hàng cùng giá trị min.
Các cách khác
1. Multi-table DELETE (JOIN)
DELETE d1 FROM DemoTable1597 d1 JOIN (SELECT MIN(Marks) AS min_mark FROM DemoTable1597) d2 ON d1.Marks = d2.min_mark LIMIT 1;
2. MySQL 8.0+: CTE
WITH min_mark AS (SELECT MIN(Marks) AS m FROM DemoTable1597) DELETE FROM DemoTable1597 WHERE Marks = (SELECT m FROM min_mark) LIMIT 1;
3. Ứng dụng: SELECT trước, DELETE sau (2 truy vấn)
SELECT MIN(Marks) INTO @min_mark FROM DemoTable1597; DELETE FROM DemoTable1597 WHERE Marks = @min_mark LIMIT 1;
Khuyên dùng: Cách bọc derived table (wrapper) đơn giản, tương thích mọi phiên bản MySQL.