Что означает операция UPSERT в контексте баз данных?

«Что означает операция UPSERT в контексте баз данных?» — вопрос из категории Базы данных, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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: Упрощает код, избегая отдельных проверок на существование и условной логики для вставки/обновления.