Урок 39. onUpgrade. Обновляем БД в SQLite

Обсуждение уроков
Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение damager82 » 05 дек 2011, 03:00

В этом уроке:

- меняем версию и обновляем структуру БД в onUpgrade

Click here to read this article!
Последний раз редактировалось damager82 01 май 2017, 16:42, всего редактировалось 7 раз.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение damager82 » 09 янв 2012, 21:39

Прочитал пост и захотелось спросить в чем предпочтение сравнения версий БД вашого метода
if (oldVersion == 1 && newVersion == 2)
перед этим
if (db.needUpgrade(new Version)) ?
В данном случае, наверно, нет разницы. Просто решил как можно более наглядно продемонстрировать что старая версия была 1, а стала 2.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение KamiSempai » 20 фев 2012, 13:36

Странно, первый вариант мне показался более логичным.
В нем мы проверяем с какой версии на какую обновляем, в то время как needUpgrade(newVersion) говорит нам, стоит обновлять или нет, а если мы в onUpgrade зашли значит обновлять нужно.
Оптимальный вариант на мой взгляд:

Код: Выделить всё

if (oldVersion <= 1) {
	// Обновляем до версии 2
}
if (oldVersion <= 2) {
	// Обновляем до версии 3
}
// И так далее...
Даже если пользователю нужно будет обновить версию базы с 1 до последней, все должно пройти идеально гладко.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение damager82 » 22 фев 2012, 09:16

KamiSempai писал(а):

Код: Выделить всё

if (oldVersion <= 1) {
	// Обновляем до версии 2
}
if (oldVersion <= 2) {
	// Обновляем до версии 3
}
// И так далее...
Даже если пользователю нужно будет обновить версию базы с 1 до последней, все должно пройти идеально гладко.
А если, например, мы во второй версии ввели новый столбец в таблицу - column2. А в третьей версии еще столбец - column3.

Тогда что писать в в ветке if (oldVersion <= 2) { ?
Если добавлять только column3, тогда не сработает обновление с первой на третью версию. column2 будет упущен.
Если добавлять и column2 и column3, тогда при обновлении с версии 2 на 3 мы снова пытаемся создать column2. Он ругнется наверно? Т.е. в этом случае могут накатиться обновления, которые уже есть. Там какие-нить коллизии могут возникнуть.

ИМХО тут надо определять разницу между версиями, например текущая - 2, обновляемая - 5. И запускать по шагам обновление с версии на версию, т.е.
2 -> 3
3 -> 4
4 -> 5

В этом случае точно никаких коллизий не будет.
Но это только мысли. На практике я пока не реализовывал такое.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение KamiSempai » 22 фев 2012, 12:44

Я понял ход Ваших мыслей. Могу сказать, что мы думаем в одном направлении.
damager82 писал(а):Тогда что писать в в ветке if (oldVersion <= 2) { ?
Добавлять столбец column3. Столбец column2 к этому времени уже будет добавлен в предыдущем условии, либо при прошлом обновлении базы, когда последней считалась версия 2.
damager82 писал(а):ИМХО тут надо определять разницу между версиями, например текущая - 2, обновляемая - 5. И запускать по шагам обновление с версии на версию, т.е.
2 -> 3
3 -> 4
4 -> 5
В моем случае так и получится. Условия идут друг за другом и ни как друг на друга не влияют. При версии - 2, условие "oldVersion <= 1" не выполнится, а "oldVersion <= 2" выполнится, и "oldVersion <= 3" выполнится по тому, что 2 <= 3.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

dlnsk
Сообщения: 9
Зарегистрирован: 13 авг 2012, 14:16

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение dlnsk » 14 авг 2012, 13:34

Насколько я понимаю средние три команды:

Код: Выделить всё

db.execSQL("drop table people;");

db.execSQL("create table people ("
              + "id integer primary key autoincrement,"
              + "name text, posid integer);");
db.execSQL("insert into people select id, name, posid from people_tmp;");
db.execSQL("drop table people_tmp;");

db.setTransactionSuccessful();
можно заменить на одну:

Код: Выделить всё

db.execSQL("drop table people;");

db.execSQL("ALTER TABLE people_tmp RENAME TO people;");

db.setTransactionSuccessful();
т.е. нет смысла создавать заново people и перегонять данные обратно (ведь структура теперь у таблиц одинаковая), а можно просто переименовать таблицу. Такая возможность наряду с добавлением поля есть.

ЗЫ: Обратил внимание на то, что people_tmp создается во временной БД. Тогда нужно поменять еще несколько строк. Итого все должно выглядеть так:

Код: Выделить всё

db.execSQL("create table people_tmp ("
              + "id integer primary key autoincrement, name text, position text, posid integer);"); //убираем temporary и добавляем опции к id

db.execSQL("insert into people_tmp select name, position, posid from people;"); //убираем поле id
db.execSQL("drop table people;");

db.execSQL("ALTER TABLE people_tmp RENAME TO people;");

db.setTransactionSuccessful();

zagidram
Сообщения: 1
Зарегистрирован: 05 ноя 2012, 19:55

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение zagidram » 05 ноя 2012, 20:09

Здравствуйте! Объясните, пожалуйста по-подробней, откуда в метод onUpgrade передаются аргументы oldVersion и newVersion. Заранее благодарю.

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение damager82 » 06 ноя 2012, 16:20

zagidram писал(а):Здравствуйте! Объясните, пожалуйста по-подробней, откуда в метод onUpgrade передаются аргументы oldVersion и newVersion. Заранее благодарю.
- при создании DBHelper вы указываете версию БД в конструкторе (newVersion)
- прога смотрит на имеющийся файл с БД, читает из него версию (oldVersion)

Две этих цифры сравниваются, если они разные, то вызывается onUpgrade. Думаю, как-то так.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Foenix » 13 дек 2012, 22:32

А как обновлять таблицу, в которой есть автоинкрементное поле?
Допустим, есть таблица заголовков, и таблица деталей - оба с инкрементным полем - первичным ключом. Вторая имеет поле-ссылку на строку в таблице заголовков.
Ведь при любом обновлении-удалении автоинкрементное поле нельзя назначить "как было".
Или можно? может быть какая-то команда есть, чтоб временно заносить туда значения во время операций обновления БД
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Roman
Сообщения: 22
Зарегистрирован: 23 авг 2012, 08:43

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Roman » 24 дек 2012, 19:04

Я читал что execSQL() медленнее стандартных методов работы с базой. Подскажите из практики когда становится не рациональным использовать execSQL(), т.к. конечно проще использовать стандартные запросы в execSQL() если знаком с синтаксисом SQL нежели стандартными методами.

Roman
Сообщения: 22
Зарегистрирован: 23 авг 2012, 08:43

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Roman » 24 дек 2012, 19:09

Olivka писал(а):А как обновлять таблицу, в которой есть автоинкрементное поле?
Допустим, есть таблица заголовков, и таблица деталей - оба с инкрементным полем - первичным ключом. Вторая имеет поле-ссылку на строку в таблице заголовков.
Ведь при любом обновлении-удалении автоинкрементное поле нельзя назначить "как было".
Или можно? может быть какая-то команда есть, чтоб временно заносить туда значения во время операций обновления БД
Поле ключей не повторяется. При обновлении ключ не меняется, т.к. его нельзя поменять, а при удалении этот ключ больше не появится. Уточните вопрос, что у вас не получается?

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Foenix » 25 дек 2012, 00:54

Roman писал(а):Я читал что execSQL() медленнее стандартных методов работы с базой. Подскажите из практики когда становится не рациональным использовать execSQL(), т.к. конечно проще использовать стандартные запросы в execSQL() если знаком с синтаксисом SQL нежели стандартными методами.
Я тут книгу читаю - базы данных в андроид (название, если интересно, могу уточнить), так вот там в конце главы эксперимент мужик проводит что быстрее - прямой запрос или джава оптимизированный, так вот прямой exec быстрее джавовского во много-много раз, например, при запросе с группировкой - в 16 раз. Он проводит этот эксперимент на таблице кажется в 17 тыс записей.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Foenix » 25 дек 2012, 00:59

Roman писал(а):
Olivka писал(а):А как обновлять таблицу, в которой есть автоинкрементное поле?
Допустим, есть таблица заголовков, и таблица деталей - оба с инкрементным полем - первичным ключом. Вторая имеет поле-ссылку на строку в таблице заголовков.
Ведь при любом обновлении-удалении автоинкрементное поле нельзя назначить "как было".
Или можно? может быть какая-то команда есть, чтоб временно заносить туда значения во время операций обновления БД
Поле ключей не повторяется. При обновлении ключ не меняется, т.к. его нельзя поменять, а при удалении этот ключ больше не появится. Уточните вопрос, что у вас не получается?
У меня не неполучается, просто я искала какой-нибудь быстрый способ.
По-другому объяснить не знаю как - случай обычный. Есть таблица с заголовками, есть таблица с деталями и полем со ссылков на таблицу с заголовками. и там и там автоинкреметное поле _id имеется, т.е. случай наираспространеннейший.
table 1
_id; name
table2
_id; name; id_table1
_id - автоинкремент в обоих случаях.

Так вот я и думала - как лучше организовать процедуру при обновлении этих таблиц (т.е. когда меняется версия базы данных, и работает процедура onUpdate). ТАм надо данные из таблиц этих выгрузить во временную, пересоздать основную таблицу а затем данные вернуть на место в новые, создавшиеся таблицы. Но когда данные загружаем обратно, то автоинкрементное поле будет иметь другие значения, и получается, что нужно их как-то сохранять, чтобы при вставке записей в подчиненную таблицу правильно заполнять это поле.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение KamiSempai » 25 дек 2012, 11:23

Olivka писал(а):Так вот я и думала - как лучше организовать процедуру при обновлении этих таблиц (т.е. когда меняется версия базы данных, и работает процедура onUpdate).
Что именно вы хотите изменить? Если что, выгружать данные во временные таблицы нужно только если необходимо удалить лишние столбцы. Для добавления столбца нужно использовать SQL команду ALTER TABLE.
И на сколько я знаю, автоинкрементное поле можно свободно перезаписывать, проблем возникнуть не должно. Нужно только следить за тем, что-бы уникальность не нарушалась, если это поле ключевое.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Foenix » 25 дек 2012, 12:51

KamiSempai писал(а): И на сколько я знаю, автоинкрементное поле можно свободно перезаписывать, проблем возникнуть не должно. Нужно только следить за тем, что-бы уникальность не нарушалась, если это поле ключевое.
В первый раз об этом слышу
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение KamiSempai » 25 дек 2012, 13:51

Olivka писал(а):В первый раз об этом слышу
Думаю, стоит это проверить.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Foenix » 25 дек 2012, 14:39

Проверила. ДУмаю, не стоит этого делать, т.к. генератор дуреет.
Например. Вношу сама значение следующего числа как 6. Затем вношу строку с пустым значением. Подтверждаю транзакцию. Генератор вносит 7-ку, вроде бы все хорошо.
окей. Вношу значение 33, подтверждаю транзакцию, затем вношу пустое значение, подтверждаю, генератор вносит 34. Опять все хорошо. Вношу значение 12, оно уникально, его нету, подтверждаю транзакцию, вместо 12-ти оказывается внесено число 34 - еще одна строка с ID 34, несмотря на то, что это PK.
Поэтому, лучше я не буду сама вносить туда числа, мало ли какой будет сбой.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение Mikhail_dev » 30 янв 2013, 14:38

А как быть с обновлением базы, которая находится на флешке и используется API7 ? Напомню, что в этом случае DBHelper идет лесом. Используется голый SQLiteDatabase. Пока в мыслях писать вручную всё это дело. В принципе не особо сложно, но может кто знает что более гуманное.

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение KamiSempai » 31 янв 2013, 00:14

no-- писал(а):А как быть с обновлением базы, которая находится на флешке и используется API7 ? Напомню, что в этом случае DBHelper идет лесом. Используется голый SQLiteDatabase. Пока в мыслях писать вручную всё это дело. В принципе не особо сложно, но может кто знает что более гуманное.
Тоже сейчас этим вопросом озадачен. Ни чего, кроме как создать специальную таблицу для хранения версии, в голову не приходит.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 39. onUpgrade. Обновляем БД в SQLite

Сообщение rezak90 » 31 янв 2013, 01:15

юзайте ormlite и будет вам счастье =)
R.id.team
Политика на форуме запрещена

Ответить