Почему sqlite застрял в прошлом и как это исправить

16.07.2026 · 5 мин

SQLite — отличный инструмент, но его дефолты могут тихо портить данные: внешние ключи выключены, типы проверяются слабо, а обновления часто ломают привычное поведение.

Первая проблема: доверие, которое sqlite не оправдывает

SQLite по умолчанию слишком многое оставляет на усмотрение разработчика. Внешние ключи нужно включать вручную через PRAGMA foreign_keys = ON;. Типовая проверка отсутствует: в колонку для INTEGER можно записать строку, и база не возразит. А при конкурирующих записях вы можете получить SQLITE_BUSY вместо ожидания.

У каждого из этих решений есть историческое объяснение, но объяснение не делает их безопасными.

БАЗА ДАННЫХ С «ДОВЕРИТЕЛЬНЫМИ» ДЕФОЛТАМИ
────────────────────────────────────────
┌──────────────┐     ┌──────────────┐
│  Пытаемся    │     │   Получаем    │
│   удалить    │────▶│    «OK»      │
│  пользователя│     │  (но данные  │
│  с постами   │     │   сломаны)   │
└──────────────┘     └──────────────┘
        │
        │ PRAGMA foreign_keys = ON
        ▼
┌──────────────┐     ┌──────────────┐
│  Пытаемся    │     │   Ошибка!    │
│   удалить    │────▶│   Данные     │
│  пользователя│     │  сохранены   │
└──────────────┘     └──────────────┘
Без включённых внешних ключей SQLite молча портит данные

Вторая проблема: глобальное выключение, а не явное включение

Mort предлагает не просто исправить дефолты, а ввести систему editions по аналогии с Rust. Идея проста: при изменении поведения базы вы явно выбираете нужную версию правил. Старый код продолжает работать по старым правилам, новый — по новым.

Это особенно важно для строгой проверки типов. Если бы SQLite поддерживал editions, можно было бы включать более жёсткое поведение только для новых проектов, не ломая миллионы существующих баз.

Третья проблема: sqlite застрял в режиме обратной совместимости

Команда SQLite справедливо указывает, что гибкая типизация удобна. Например, можно хранить даты в колонке DATETIME и сериализовать их на уровне приложения. Но у этого подхода есть цена: слабые гарантии целостности и постоянный риск неожиданных ошибок.

Стандарт SQL уже давно предусматривает домены — пользовательские типы с ограничениями. Поддержка CREATE DOMAIN позволила бы сохранить гибкость там, где она нужна, и при этом сделать поведение базы более строгим и предсказуемым.

ПУТЬ РАЗВИТИЯ БАЗЫ ДАННЫХ
──────────────────────────
Без editions:    Все версии ▼ Новая версия = Поломка
                 [███████][████][████][████][████][XXXX]

С editions:      Edition 1    │  Edition 2   │  Edition 3
                 [██████████] │ [██████████]│ [██████████]
                 Миграция явная, контролируемая
Editions позволяют эволюционировать базу данных без катастрофических обновлений

Практический вывод

SQLite остаётся мощной и полезной базой данных, но его исторические компромиссы сегодня всё чаще становятся источником проблем. Идея editions выглядит не утопией, а практичным способом развивать систему без массовых поломок.

Если нужен более строгий режим уже сейчас, можно использовать STRICT при создании таблицы. Это простой способ получить более надёжное поведение без ожидания будущих изменений в самой SQLite.

Ссылки

Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.