sqlite и ошибка «ограничение не выполнено» при одновременном выборе и вставке - PullRequest
6 голосов
/ 16 марта 2011

Я работаю над функцией миграции.Он читает данные из старой таблицы и вставляет их в новую.Все эти вещи работают в фоновом потоке с низким приоритетом.

Мои шаги в псевдокоде.

sqlite3_prepare_stmt (select statement)
sqlite3_prepare_stmt (insert statement)

while (sqlite3_step (select statement) == SQLITE_ROW)
{
    get data from select row results
    sqlite3_bind select results to insert statement
    sqlite3_step (insert statement)
    sqlite3_reset (insert statement)
}

sqlite3_reset (select statement)

Я всегда получаю ошибку «Сбой ограничения» на sqlite3_step (insert statement).Почему это произошло и как я могу это исправить?

UPD: Как я понимаю, это случилось, потому что фоновый поток использует дескриптор db, открытый в основном потоке.Теперь проверяем это предположение.

UPD2:

sqlite> select sql from sqlite_master where tbl_name = 'tiles';
CREATE TABLE tiles('pk' INTEGER PRIMARY KEY, 'data' BLOB, 'x' INTEGER, 'y' INTEGER, 'z' INTEGER, 'importKey' INTEGER)
sqlite> select sql from sqlite_master where tbl_name = 'tiles_v2';
CREATE TABLE tiles_v2 (pk int primary key, x int, y int, z int, layer int, data blob, timestamp real)

Ответы [ 5 ]

9 голосов
/ 16 марта 2011

Это, вероятно, означает, что ваш оператор вставки нарушает ограничение в новой таблице.Может быть ограничение первичного ключа, ограничение уникальности, ограничение внешнего ключа (если вы используете PRAGMA foreign_keys = ON;) и т. Д.

Это можно исправить, удалив ограничение, исправив данные илисбросив данные.Отбрасывание ограничения, как правило, плохо, но это зависит от приложения.

Есть ли веская причина копировать данные по одной строке за раз вместо набора?

INSERT INTO new_table
SELECT column_list FROM old_table;

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

select sql from sqlite_master where tbl_name = 'old_table_name';
select sql from sqlite_master where tbl_name = 'new_table_name';

Обновление: На основе результатов этих двухзапросы, я вижу только одно ограничение - ограничение первичного ключа в каждой таблице.Если вы не создали никаких триггеров для этих таблиц, единственным ограничением, которое может дать сбой, является ограничение первичного ключа.И единственный способ, которым ограничение может потерпеть неудачу, - это если вы попытаетесь вставить две строки, которые имеют одинаковое значение для 'pk'.

Я полагаю, это может произойти несколькими различными способами.

  • В старой таблице есть повторяющиеся значения в столбце 'pk'.
  • Код, который выполняет миграцию, изменяет или вводит повторяющееся значение перед вставкой данных в новую таблицу.
  • Другой процесс,возможно, работает на другом компьютере, вставляет или обновляет данные без вашего ведома.
  • Другие причины, о которых я пока не задумывался.: -)

Вы можете определить, есть ли в старой таблице повторяющиеся значения 'pk', выполнив этот запрос.

select pk 
from old_table_name
group by pk
having count() > 1;

Возможно, вы попытаетесь вручную перенестииспользование данных INSERT INTO . . . SELECT . . . Если это не удается, добавьте предложение WHERE, чтобы уменьшить размер набора, пока вы не изолируете неверные данные.

2 голосов
/ 09 февраля 2017

На всякий случай, если кто-нибудь приземлится здесь в поисках сообщения об ошибке «Сбой ограничения», убедитесь, что тип вашего столбца Id равен INTEGER, а не INTEGER (0, 15) или что-то в этом роде.

Фон

Если в вашей таблице есть столбец с именем Id, с типом INTEGER и установленным в качестве первичного ключа, SQLite обрабатывает его как псевдоним для встроенного столбца RowId. Этот столбец работает как столбец с автоинкрементом. В моем случае этот столбец работал нормально, пока какой-то дизайнер таблиц (вероятно, созданный парнями из SQLite для Visual Studio) не изменил тип столбца с INTEGER на INTEGER (0, 15), и внезапно мое приложение начало выдавать исключение Constraint failed.

1 голос
/ 17 апреля 2018

просто для большей ясности:
убедитесь, что вы используете правильный тип данных, я использовал int вместо integer при создании таких таблиц tmy:

id int primary key not null

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

0 голосов
/ 13 марта 2019

Я обнаружил, что устранение ошибок ограничения внешнего ключа с помощью sqlite может быть проблематичным, особенно для больших наборов данных. Однако следующий подход помогает выявить оскорбительное отношение.

  1. отключить проверку внешнего ключа: PRAGMA foreign_keys = 0;
  2. выполнить инструкцию, которая вызывает ошибку - в моем случае это была ВСТАВКА из 70000 строк с 3 различными отношениями внешнего ключа.
  3. включить проверку внешнего ключа: PRAGMA foreign_keys = 1;
  4. выявить ошибки внешнего ключа: PRAGMA foreign_key_check(table-name);

В моем случае было показано 13 строк с недействительными ссылками.

0 голосов
/ 06 мая 2018

Одной из причин возникновения этой ошибки является вставка дублированных данных для уникальной строки. Проверьте все свои уникальные и ключи для дублированных данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...