JuniorKỹ thuậtSQL
Bạn viết upsert trong SQL như thế nào?
Thử trả lời trước
Đáp án mẫu
Upsert là insert một dòng, hoặc update nó nếu đã tồn tại. Nó cần một unique key để phát hiện xung đột, và mỗi engine có cú pháp riêng.
-- PostgreSQL, SQLite
INSERT INTO stock (sku, qty) VALUES ('A1', 5)
ON CONFLICT (sku) DO UPDATE SET qty = EXCLUDED.qty;
-- MySQL 8
INSERT INTO stock (sku, qty) VALUES ('A1', 5) AS new
ON DUPLICATE KEY UPDATE qty = new.qty;
Dạng chuẩn SQL là MERGE, có trong SQL Server, Oracle và PostgreSQL 15+. Nó linh hoạt hơn, với các nhánh riêng cho dòng khớp và không khớp.
Đừng viết kiểu "select rồi insert hoặc update" trong code ứng dụng. Hai request đồng thời cùng thấy chưa có dòng và cùng insert, dẫn đến lỗi duplicate key hoặc, nếu không có constraint, dữ liệu trùng. Upsert của database mang tính atomic và xử lý được race này.
Dùng DO NOTHING (hoặc INSERT IGNORE) khi chỉ muốn bỏ qua các dòng đã có.
Upsert chỉ an toàn bằng unique constraint đứng sau nó.
Ý chính
- Upsert cần unique key để phát hiện xung đột
- Cú pháp khác nhau - ON CONFLICT, ON DUPLICATE KEY, MERGE
- Upsert của database là atomic, select rồi ghi thì bị race
Câu hỏi nối tiếp thường gặp
- Giá trị auto-increment ra sao khi upsert gặp xung đột?
Lỗi thường gặp
- Kiểm tra tồn tại trong code ứng dụng trước khi insert
- Chạy upsert mà không có unique constraint trên key