SQLite LinuxWindowsmacOS

Исправление SQLite foreign key mismatch при изменении PRIMARY KEY

  • Обновлено
  • Чтение ≈ 3 минуты

Краткий ответ

«foreign key mismatch» отличается от «FOREIGN KEY constraint failed»: SQLite не может сопоставить объявление внешнего ключа дочерней таблицы с подходящим первичным или уникальным ключом родителя. Сбой может проявиться только при INSERT/UPDATE/DELETE после изменения PRIMARY KEY, удаления UNIQUE либо смены коллации. Удалять строки ребёнка или выключать контроль внешних ключей — неправильное первое действие.

В этой статье
  1. Что происходит и когда возникает
  2. Возможные причины: как различить
  3. Пошаговая диагностика и исправление
  4. Команды и проверочные примеры
  5. Как проверить результат
  6. Если не помогло

#Что происходит и когда возникает

«foreign key mismatch» отличается от «FOREIGN KEY constraint failed»: SQLite не может сопоставить объявление внешнего ключа дочерней таблицы с подходящим первичным или уникальным ключом родителя. Сбой может проявиться только при INSERT/UPDATE/DELETE после изменения PRIMARY KEY, удаления UNIQUE либо смены коллации. Удалять строки ребёнка или выключать контроль внешних ключей — неправильное первое действие.

#Возможные причины: как различить

Возможная причинаКак узнатьЧто делать
Ссылка осталась на старый ключМиграция изменила имя/число полей PRIMARY KEY в родительской таблице, а дочерняя схема не обновлена.PRAGMA foreign_key_list(child) показывает старые поля; sqlite_schema содержит новый родительский ключ.Согласованно пересоздать внешние ключи в миграции.
Родительский ключ больше не уникальныйFOREIGN KEY может ссылаться только на PRIMARY KEY или подходящий UNIQUE с корректной collation.В schema нет UNIQUE на указанных полях или коллация индекса и колонок различается.Исправить родительский ключ и связи, не маскируя проблему.
Другое число столбцов составного ключаВ объявлении REFERENCES не указаны колонки, а PRIMARY KEY родителя состоит из нескольких.Количество колонок дочернего FK не соответствует составному PK.Сопоставить все колонки явно и проверить типы.

#Пошаговая диагностика и исправление

  1. Остановите изменение данных по ошибочной связиЕсли ошибка появилась после миграции, отключите именно проблемную операцию приложением, не отключая внешние ключи во всей базе. Запишите таблицу, текст ошибки и недавнее изменение схемы. Чтение данных и резервное копирование обычно остаются возможны.
  2. Проверьте, к какой базе подключеныВ SQL-консоли нужного приложения выполните PRAGMA database_list;. Сверьте путь основной базы с настройками. Затем запросите SELECT name,sql FROM sqlite_schema WHERE type='table' AND name IN ('parent','child');, подставив имена своих таблиц; это покажет исходные определения.
  3. Посмотрите фактическое объявление внешнего ключаВыполните PRAGMA foreign_key_list(child);. В ответе сравните столбцы from (дочерняя таблица) и to (родительская). Если to пуст, ссылка идёт на PRIMARY KEY родителя. Проверьте PRAGMA table_info(parent); и PRAGMA index_list(parent);, не делая изменений.
  4. Проверьте индексы и совпадение полейЕсли связь направлена не на PRIMARY KEY, найдите соответствующий UNIQUE-индекс, состав колонок и collation через PRAGMA index_xinfo(имя_индекса);. Для составного ключа важны все поля и их число. Не добавляйте случайный UNIQUE: на реальных данных он может не создаться из-за повторов.
  5. Подготовьте копию перед миграциейСоздайте резервную копию SQLite через Online Backup API и проверьте PRAGMA integrity_check;. На копии проверьте PRAGMA foreign_key_check; — он диагностирует значения связей, но при неверной схеме сам может сообщить mismatch. Отдельно зафиксируйте строки, которые требуют сопоставления новых ключей.
  6. Исправьте связь согласованной миграциейЕсли поменялся PK, спроектируйте пересоздание дочерней таблицы с правильным REFERENCES и копированием строк, соблюдая документированную последовательность SQLite для изменения схемы. Это работа миграции, а не отдельная универсальная команда ALTER COLUMN: SQLite не поддерживает произвольный ALTER CONSTRAINT для такой правки. Убедитесь, что старые идентификаторы сопоставлены новым и нет потерянных строк.
  7. Проверьте тестовую миграциюНа копии включите PRAGMA foreign_keys=ON; до начала транзакций, затем выполните тестовые INSERT/UPDATE по штатному сценарию. Пустой результат PRAGMA foreign_key_check и отсутствие foreign key mismatch в приложении подтверждают исправление. Если ошибка остаётся, остановите перенос и вернитесь к схеме до миграции.

#Команды и проверочные примеры

SQLКоманда
Подставьте реальные имена child/parent, выполняйте в нужной базе; запросы не изменяют строки.
PRAGMA foreign_key_list(child);
PRAGMA table_info(parent);
PRAGMA index_list(parent);
PRAGMA foreign_key_check;
SQL
Только в чистой тестовой базе: это корректная схема с согласованной ссылкой на ключ p(id).
PRAGMA foreign_keys = ON;
CREATE TABLE p(id INTEGER PRIMARY KEY, code TEXT);
CREATE TABLE c(id INTEGER PRIMARY KEY, parent_id INTEGER REFERENCES p(id));
INSERT INTO p(id, code) VALUES(1, 'A');
INSERT INTO c(id, parent_id) VALUES(1, 1);
PRAGMA foreign_key_check;

#Как проверить результат

После миграции PRAGMA foreign_key_list показывает точный родительский столбец; PRAGMA foreign_key_check не возвращает нарушений; разрешённая тестовая вставка проходит, а неправильная ссылка отклоняется как FOREIGN KEY constraint failed (в отличие от mismatch).

#Если не помогло

Если появились несопоставленные записи, прервите миграцию и составьте таблицу соответствия старых и новых ключей; не удаляйте данные для устранения ошибки. Передайте схему обеих таблиц и индексов ответственному разработчику.

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.