Luôn test UPDATE/DELETE với SELECT trước — UPDATE users SET active = false thiếu WHERE cập nhật TOÀN BỘ bảng; dùng RETURNING để verify rows affected; ON CONFLICT cho atomic upsert.
- Bulk INSERT:
INSERT INTO users (name, email) VALUES ('A', 'a@x.com'), ('B', 'b@x.com'), ('C', 'c@x.com')— một round-trip thay vì N trips, nhanh hơn 10-100x với lượng lớn. - RETURNING clause (PostgreSQL):
INSERT INTO users (name) VALUES ('Dinh') RETURNING id, created_at— lấy generated values ngay không cần query thêm. - ON CONFLICT (upsert):
INSERT INTO settings (user_id, key, value) VALUES (1, 'theme', 'dark') ON CONFLICT (user_id, key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()— atomic upsert không race condition. - Safe UPDATE: luôn chạy SELECT với WHERE condition trước để verify rows affected;
UPDATE users SET role = 'admin' WHERE id = 5 RETURNING *confirm kết quả. - Safe DELETE:
BEGIN; DELETE FROM users WHERE created_at < '2020-01-01'; SELECT COUNT(*); ROLLBACK;— dry run trong transaction để kiểm tra trước khi COMMIT.
Pitfall: UPDATE users SET active = false không có WHERE → update toàn bộ bảng, không thể undo nếu không có backup; dùng sql_safe_updates mode hoặc review trước khi execute.