Để thực hiện INSERT chỉ khi bảng chưa có dữ liệu nào, bạn dùng subquery với NOT EXISTS.
Cú pháp
INSERT INTO ten_bang (ten_cot)
SELECT 'gia_tri_moi'
WHERE NOT EXISTS (SELECT * FROM ten_bang);
Cơ chế hoạt động
SELECT 'gia_tri_moi'trả về 1 hàng với giá trị cần chènWHERE NOT EXISTS (...)chỉ trả về hàng đó nếu bảng rỗng- Nếu bảng đã có dữ liệu → subquery trả về hàng → NOT EXISTS = FALSE → không chèn
Ví dụ minh họa
1. Tạo bảng
CREATE TABLE ExecuteInsertDemo (
Name VARCHAR(20)
);
2. Trường hợp 1: Bảng ĐÃ CÓ dữ liệu
INSERT INTO ExecuteInsertDemo VALUES('John'); -- Bảng có 1 hàng
INSERT INTO ExecuteInsertDemo(Name)
SELECT 'Larry'
WHERE NOT EXISTS (SELECT * FROM ExecuteInsertDemo);
Kết quả: Query OK, 0 rows affected - Không chèn được.
SELECT * FROM ExecuteInsertDemo;
+------+
| Name |
+------+
| John |
+------+
3. Trường hợp 2: Bảng RỖNG
TRUNCATE TABLE ExecuteInsertDemo; -- Xóa sạch dữ liệu
INSERT INTO ExecuteInsertDemo(Name)
SELECT 'Larry'
WHERE NOT EXISTS (SELECT * FROM ExecuteInsertDemo);
Kết quả: Query OK, 1 row affected - Chèn thành công.
SELECT * FROM ExecuteInsertDemo;
+-------+
| Name |
+-------+
| Larry |
+-------+
Các biến thể hữu ích
Chèn nhiều cột
INSERT INTO users (username, email, role)
SELECT 'admin', 'admin@example.com', 'admin'
WHERE NOT EXISTS (SELECT * FROM users);
Chèn nhiều hàng cùng lúc (batch) khi bảng rỗng
INSERT INTO config (config_key, config_value)
SELECT * FROM (
SELECT 'site_name', 'My Website' UNION ALL
SELECT 'version', '1.0.0' UNION ALL
SELECT 'debug', 'false'
) AS tmp
WHERE NOT EXISTS (SELECT * FROM config);
Kết hợp với IGNORE (bỏ qua trùng khóa chính)
INSERT IGNORE INTO ten_bang (id, ten_cot)
SELECT 1, 'gia_tri'
WHERE NOT EXISTS (SELECT * FROM ten_bang WHERE id = 1);
Lưu ý hiệu năng
NOT EXISTS (SELECT * FROM bang)dừng lại ngay khi tìm thấy 1 hàng (không quét toàn bảng)- Hiệu quả hơn
NOT EXISTS (SELECT 1 FROM bang LIMIT 1)(MySQL tối ưu tự động) - Với bảng lớn, đảm bảo có index phù hợp cho các cột trong subquery
Ứng dụng thực tế
- Khởi tạo dữ liệu mặc định (seed data) khi deploy lần đầu
- Cài đặt cấu hình hệ thống (settings) chỉ tạo 1 lần
- Tạo record admin mặc định
- Migration script an toàn chạy nhiều lần