Ответ
UPSERT — это гибридная операция, объединяющая INSERT (вставка новой записи) и UPDATE (обновление существующей). Её логика: "Если запись с таким ключом существует — обнови её, если нет — вставь новую". Это стандартный паттерн для обеспечения идемпотентности операций.
Реализация в различных технологиях:
1. SQL (SQLite, PostgreSQL):
Используется синтаксис INSERT ... ON CONFLICT. Конфликт определяется по PRIMARY KEY или другому уникальному ограничению.
-- SQLite / PostgreSQL
INSERT INTO users (id, name, email)
VALUES (123, 'Alice', 'alice@example.com')
ON CONFLICT(id) DO UPDATE
SET name = excluded.name,
email = excluded.email;
2. Core Data (Swift): Нативного UPSERT нет, паттерн реализуется через fetch-проверку.
let context = persistentContainer.viewContext
let userId = "123"
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "id == %@", userId)
if let existingUser = try? context.fetch(fetchRequest).first {
// UPDATE: Обновляем найденный объект
existingUser.name = "Alice"
existingUser.email = "alice@example.com"
} else {
// INSERT: Создаем новый объект
let newUser = User(context: context)
newUser.id = userId
newUser.name = "Alice"
newUser.email = "alice@example.com"
}
try? context.save()
3. Swift (UserDefaults / in-memory): Паттерн остается тем же: проверить существование ключа, затем обновить или установить значение.
var userDictionary = [String: Any]()
let key = "user_123"
// UPSERT
userDictionary[key] = ["name": "Alice", "email": "alice@example.com"]
Преимущество UPSERT: Упрощает код, избегая отдельных проверок на существование и условной логики для вставки/обновления.