MySQL cho phép kết hợp INSERT ... SELECT với UNION ALL để chèn dữ liệu từ một nguồn vào nhiều bảng, hoặc chèn nhiều tập kết quả khác nhau vào cùng một bảng — tất cả trong một câu lệnh duy nhất.
Ví dụ minh họa
Tạo bảng đích (DemoTable1):
mysql> CREATE TABLE DemoTable1 (
StudentName VARCHAR(20),
StudentMarks INT
);
Tạo bảng nguồn (DemoTable2):
mysql> CREATE TABLE DemoTable2 (
Name VARCHAR(20)
);
Chèn 1 hàng vào bảng nguồn:
mysql> INSERT INTO DemoTable2 VALUES ('Chris');
INSERT vào DemoTable1 từ DemoTable2 với 2 giá trị Marks khác nhau (UNION ALL)
mysql> INSERT INTO DemoTable1
SELECT Name, 89 FROM DemoTable2
UNION ALL
SELECT Name, 98 FROM DemoTable2;
Kết quả: 2 hàng được chèn vào DemoTable1:
mysql> SELECT * FROM DemoTable1;
+-------------+--------------+ | StudentName | StudentMarks | +-------------+--------------+ | Chris | 89 | | Chris | 98 | +-------------+--------------+
Giải thích
SELECT Name, 89 FROM DemoTable2: Tạo hàng (Chris, 89).SELECT Name, 98 FROM DemoTable2: Tạo hàng (Chris, 98).UNION ALL: Gộp 2 tập kết quả (giữ trùng lặp — ở đây không trùng).INSERT INTO DemoTable1 ...: Chèn toàn bộ kết quả gộp vào bảng đích.
UNION ALL vs UNION
| Toán tử | Xử lý trùng lặp | Hiệu năng | Khi nào dùng |
|---|---|---|---|
UNION ALL | Giữ tất cả (không loại trùng) | Nhanh hơn (không sort/unique) | Biết chắc không trùng, hoặc muốn giữ trùng |
UNION | Loại trùng (DISTINCT) | Chậm hơn (cần sort/hash) | Cần kết quả duy nhất |
Mở rộng: INSERT vào 2 bảng khác nhau cùng lúc
MySQL không hỗ trợ INSERT INTO table1, table2 ... trong một câu lệnh. Giải pháp:
- Transaction: Bọc 2 INSERT riêng biệt trong
START TRANSACTION ... COMMIT. - Trigger: AFTER INSERT trên bảng 1 → INSERT vào bảng 2.
- Application layer: Gọi 2 INSERT từ code ứng dụng trong 1 transaction.
- Stored Procedure: Góc 2 INSERT trong 1 proc.
Ví dụ thực tế: Tạo bản ghi log + dữ liệu chính
INSERT INTO Orders (CustomerId, Amount, Status)
SELECT CustomerId, Amount, 'Pending' FROM TempOrders
UNION ALL
SELECT CustomerId, Amount, 'Pending' FROM TempOrders2;
-- Hoặc dùng CTE (MySQL 8.0+)
WITH Combined AS (
SELECT CustomerId, Amount FROM TempOrders
UNION ALL
SELECT CustomerId, Amount FROM TempOrders2
)
INSERT INTO Orders (CustomerId, Amount, Status)
SELECT CustomerId, Amount, 'Pending' FROM Combined;