Ковыряясь с базами данных в Android, я столкнулся с очень неприятной вещью: методы SQLiteDatabase для вставки данных работают не совсем так, как написано в документации.
Задача была проста: вставить запись и получить ее ключ для использования в другой таблице.
Если требуемая запись уже существует, вам необходимо узнать ключ этой старой записи.
Оказалось, что получить можно всё, кроме этого очень старого ключа.
Чтобы разобраться в этом, мне пришлось провести несколько экспериментов на кошках, но теперь кое-что стало яснее.
Для начала посмотрим, что обещает нам Android в SQLiteDatabase: вставлять() - самый простой метод. Должен вернуть только что вставленный ключ или -1, если что-то пошло не так.
вставитьOrThrow() — описание точно соответствует предыдущему, но добавлено, что метод выбрасывает SQLException. Судя по названию, вы можете ожидать, что вместо возврата -1 будет выброшено SQLException, но мы пока не уверены.
вставитьВиОнКонфликт() - это самое интересное.
Нам обещают, что метод вернет ключ новой записи ИЛИ ключ существующей записи, если для конфликтов использовался алгоритм IGNORE ИЛИ -1. Также запомним, что здесь ничего не сказано о SQLException. Теперь посмотрим, что происходит на практике.
Давайте создадим простую таблицу и попробуем задать для нее разные алгоритмы разрешения конфликтов (в том числе и ни одного).
Откат и аборт я не проверял — их поведение в этом случае, судя по всему, будет аналогично фейлу, а меня больше всего интересовал игнор.
Давайте вставим в таблицу несколько уникальных значений, а затем попробуем добавить конфликтующее.
Давайте посмотрим, как все эти методы обрабатывают конфликты.
Если алгоритм разрешения конфликтов не указан, простой метод Insert() возвращает -1 (как и было обещано), а методы InsertOrThrow() и InsertWithOnConflict() вызывают исключение SQLiteConstraintException. И если это верно для метода InsertOrThrow(), то от метода InsertWithOnConflict() можно ожидать -1. То же самое происходит и с алгоритмом «провал».
Алгоритм замены сработал нормально — все методы удалили старую запись, вставили новую и вернули ее ключ.
А вот с таким необходимым «игнором» получился полный облом.
Ни один метод не выдал ошибку (-1 или SQLiteConstraintException).
Все единогласно вернули какое-то число — предположительно ключ последней записи, вставленной в таблицу.
Конечно, это совсем не то, что нам обещали.
В общем, документации доверять нельзя.
Любой метод может либо вернуть самые неожиданные значения, либо выдать исключение.
Но желаемого результата добиться не удалось — ни один метод не смог вернуть ключ существующей записи в случае конфликта.
Теги: #Android #SQLite #Разработка для Android
-
Архит
19 Oct, 24 -
Умный Дом На Базе Контроллера Amx Ni-3100
19 Oct, 24 -
Современная Офисная Инфраструктура - 1
19 Oct, 24 -
Вы Верите В Популярность Windows 7?
19 Oct, 24 -
C#: Коллекции Только Для Чтения И Lsp
19 Oct, 24 -
Аккордеон Выпущен Для Ipad И Iphone
19 Oct, 24 -
О Фантиках, Окрошке И Инвестициях
19 Oct, 24