Vấn đề: Tự động sinh UserId dạng '001', '002'... khi chèn hàng mới
Cần UserId VARCHAR(20) có 3 chữ số, điền 0 đầu, tự động tăng dựa trên MAX(Id) hiện có.
Giải pháp: INSERT INTO SELECT + LPAD + COALESCE
1. Tạo bảng
CREATE TABLE DemoTable (
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
UserId VARCHAR(20)
);
2. Chèn hàng đầu tiên (bảng rỗng)
INSERT INTO DemoTable (UserId)
SELECT LPAD(COALESCE(MAX(Id), 0) + 1, 3, '0') FROM DemoTable;
3. Lặp lại 2 lần nữa
INSERT INTO DemoTable (UserId)
SELECT LPAD(COALESCE(MAX(Id), 0) + 1, 3, '0') FROM DemoTable;
INSERT INTO DemoTable (UserId)
SELECT LPAD(COALESCE(MAX(Id), 0) + 1, 3, '0') FROM DemoTable;
4. Kết quả
+----+--------+
| Id | UserId |
+----+--------+
| 1 | 001 |
| 2 | 002 |
| 3 | 003 |
+----+--------+
Giải thích
MAX(Id)– Lấy ID lớn nhất hiện có (kiểu INT).COALESCE(MAX(Id), 0)– Nếu bảng rỗng, MAX trả NULL → COALESCE chuyển thành 0.+ 1– Số thứ tự tiếp theo.LPAD(..., 3, '0')– Đệm trái chuỗi '0' để đủ 3 ký tự.
Cảnh báo: Race Condition (Điều kiện đua)
Cách này KHÔNG AN TOÀN cho môi trường đa người dùng (concurrent inserts). Hai session cùng đọc MAX(Id) = 3, cùng chèn '004' → trùng UserId.
Giải pháp an toàn
- Dùng cột
Id INT AUTO_INCREMENTlàm khóa chính thực sự. - Tạo
UserIdlàGENERATED ALWAYS AS (LPAD(Id, 3, '0')) STORED(MySQL 5.7+). - Hoặc dùng
SEQUENCE(MariaDB 10.3+, MySQL 8.0 không có sequence chuẩn).