Можно ли положиться на SQLiteConstraint и позволить SQLite выполнить проверку для меня?Есть ли подвох? - PullRequest
8 голосов
/ 01 января 2012

У меня есть база данных SQLite в Android, и я использую ContentProvider для обработки операций, которые сохраняются в таблице с квалификатором UNIQUE в столбце.

Проблема:

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

Вопрос:

Итак, как мне замолчать эти журналылинии?Это вообще возможно?

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

Ошибка:

Столбец времени имеет ограничение UNIQUE:

Error inserting Factor=2.0 Time=1325375465000 Extra=none
android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
    at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
    at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:55)
    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1549)
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1410)
    at mypackage.myapp.provider.DataProvider.bulkInsert(DataProvider.java:353)
    at android.content.ContentProvider$Transport.bulkInsert(ContentProvider.java:179)
    at android.content.ContentResolver.bulkInsert(ContentResolver.java:646)
    at mypackage.myapp.service.MyService.onHandleIntent(MyService.java:96)
    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.os.HandlerThread.run(HandlerThread.java:60)

Ответы [ 3 ]

10 голосов
/ 01 января 2012

Если вы можете сформулировать или изменить SQL самостоятельно, либо для INSERT, либо для начального CREATE TABLE, вы можете использовать расширение обработки конфликтов SQLite . Есть два варианта, как это сделать:

  • При вставке используйте INSERT OR IGNORE вместо INSERT. Вы также можете использовать OR REPLACE, OR ABORT или любую другую реакцию.
  • При создании таблицы укажите предложение ON CONFLICT IGNORE для ограничения UNIQUE. Это заставит вставки или обновления, которые нарушают ограничение, ничего не делать.

Мне кажется, что идея использования INSERT OR IGNORE / INSERT OR REPLACE для обработки дублирующихся данных, особенно в параллельных средах, очень чистая. Он проверяет дублирование один раз - в базе данных - и избегает условий гонки, когда вы сначала проверяете существование (по общему признанию, это не проблема, если только один процесс / поток обращается к базе данных).

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

4 голосов
/ 04 октября 2012

Использование SQLiteDatabase.insertOrThrow(...)

1 голос
/ 01 января 2012

Да, вы можете оставить это и, как вы говорите, вы можете это исправить. По моему мнению, это зависит от того, являются ли эти случаи исключительными или «просто случаются, потому что ты ленивый».

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

...