Когда запускается SQLiteOpenHelper onCreate () / onUpgrade ()?

247

Я создал свои таблицы в моем SQLiteOpenHelper onCreate() но получаю

SQLiteException: no such table

или же

SQLiteException: no such column

ошибки. Зачем?

НОТА:

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

  • 0
    Вы можете разместить код?
  • 12
    @Ndupza Это не моя проблема, просто надоело писать один и тот же ответ / комментарий в N-й раз.
Теги:
android-sqlite
sqlexception
sqliteopenhelper

14 ответов

347
Лучший ответ

SQLiteOpenHelper onCreate() и onUpgrade() вызываются, когда база данных фактически открывается, например, путем вызова getWritableDatabase(). База данных не открывается, когда создается объект-помощник базы данных.

SQLiteOpenHelper версии файлов базы данных. Номер версии - это аргумент int, переданный конструктору . В файле базы данных номер версии хранится в PRAGMA user_version.

onCreate() запускается только тогда, когда файл базы данных не существует и только что был создан. Если onCreate() успешно возвращается (не генерирует исключение), предполагается, что база данных будет создана с запрошенным номером версии. Как следствие, вы не должны ловить SQLException в onCreate() самостоятельно.

onUpgrade() вызывается только тогда, когда существует файл базы данных, но номер сохраненной версии ниже запрошенного в конструкторе. onUpgrade() должен обновить схему таблицы до требуемой версии.

При изменении схемы таблицы в коде (onCreate()) вы должны убедиться, что база данных обновлена. Два основных подхода:

  • Удалите старый файл базы данных, чтобы onCreate() снова запускался. Это часто бывает предпочтительным во время разработки, когда вы контролируете установленные версии и потеря данных не является проблемой. Некоторые способы удаления файла базы данных:

    • Удалите приложение. Используйте диспетчер приложений или adb uninstall your.package.name из оболочки.

    • Очистить данные приложения. Используйте диспетчер приложений.

  • Увеличьте версию базы данных, чтобы вызвать onUpgrade(). Это немного сложнее, так как требуется больше кода.

    • При обновлении схемы времени разработки, где потеря данных не является проблемой, вы можете просто использовать execSQL("DROP TABLE IF EXISTS <tablename>") для удаления существующих таблиц и вызвать onCreate() для воссоздания базы данных.

    • Для выпущенных версий вы должны реализовать миграцию данных в onUpgrade(), чтобы ваши пользователи не теряли свои данные.

  • 2
    @Laalto // перенос данных в onUpgrade () // Можете ли вы объяснить это.
  • 2
    @bala Не в рамках этого вопроса / ответа. Если у вас есть вопрос, не стесняйтесь отправить его как вопрос.
Показать ещё 5 комментариев
89

Для дальнейшего добавления недостающих точек здесь, в соответствии с запросом Jaskey

Версия базы данных хранится в файле базы данных SQLite.

catch - это конструктор

SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

Поэтому, когда конструктор вспомогательной базы данных вызывается с name (второй параметр), платформа проверяет, существует ли база данных или нет, и если база данных существует, она получает информацию о версии из заголовка файла базы данных и запускает правильный вызов назад

Как уже объяснялось в более старшем ответе, если база данных с именем не существует, она запускает onCreate.

Ниже объясняется пример onUpgrade с примером.

Скажем, ваша первая версия приложения имела DatabaseHelper (расширение SQLiteOpenHelper) с версией для передачи конструктора как 1, а затем вы предоставили обновленное приложение с новым исходным кодом, имеющим версию, прошедшую как 2, затем автоматически, когда построено DatabaseHelper, триггеры платформы onUpgrade, увидев, что файл уже существует, но версия ниже текущей версии, которую вы передали.

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

Пример псевдо-кода ниже:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  switch(oldVersion) {
    case 1:
       //upgrade logic from version 1 to 2
    case 2:
       //upgrade logic from version 2 to 3
    case 3:
       //upgrade logic from version 3 to 4
       break;
    default:
       throw new IllegalStateException(
                "onUpgrade() with unknown oldVersion " + oldVersion);
  }
}

Обратите внимание на отсутствующий оператор break в случае 1 и 2. Это то, что я подразумеваю под инкрементным обновлением.

Скажем, если старая версия 2, а новая версия - 4, то логика обновит базу данных с 2 до 3, а затем до 4

Если старая версия 3 и новая версия 4, она просто запустит логику обновления для 3 до 4

  • 1
    Я думаю, вы хотите, чтобы ваш переключатель (newVersion) был переключателем (oldVersion). Вы также можете проверить, что newVersion равно 4 (а не 5 или 3; поскольку ваша логика предполагает, что новая версия должна быть 4). Как и раньше, если старая версия 2, а новая версия 5, вы ударить по делу 4: и обновить с 3 до 4 (что, вероятно, не следует ожидать поведения).
  • 0
    правильно - опечатка .. но если новая версия 5 ->, то она всегда выдаст исключение IllegalStateException, и разработчик исправит это, добавив случай 5 ..
Показать ещё 2 комментария
19

onCreate()

  • Когда мы создаем базу данных в первый раз (т.е. база данных не существует) onCreate() создайте базу данных с версией, которая передается в SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

  • onCreate() метод создает таблицы, которые вы определили и выполняете любой другой написанный вами код. Однако этот метод вызывается только в случае отсутствия файла SQLite в каталоге данных ваших приложений (/data/data/your.apps.classpath/databases).

  • Этот метод не будет вызываться, если вы изменили свой код и перезапустили его в эмуляторе. Если вы хотите выполнить onCreate(), вам нужно использовать adb для удаления файла базы данных SQLite.

onUpgrade()

  • SQLiteOpenHelper должен вызвать супер конструктор.
  • Метод onUpgrade() вызывается только тогда, когда целое число версии больше, чем текущая версия, запущенная в приложении.
  • Если вы хотите вызвать метод onUpgrade(), вам необходимо увеличить номер версии в своем коде.
  • 1
    Не могли бы вы более подробно изложить свой ответ, добавив немного больше описания предлагаемого вами решения?
8

Может быть, я слишком поздно, но я хотел бы поделиться своим коротким и сладким ответом. Пожалуйста, проверьте Отвечать на ту же проблему. Это определенно поможет вам. Нет более глубоких спецификаций.

Если вы уверены в синтаксисе создания таблицы, это может произойти, когда вы добавляете новый столбец в свою же таблицу, для этого...

1) Удалите с устройства и запустите его снова.

ИЛИ

2) Настройка → приложение → ClearData​​strong >

ИЛИ

3) Измените DATABASE_VERSION в своем классе DatabaseHandler (если вы добавили новый столбец, который автоматически обновится)

public DatabaseHandler(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

ИЛИ

4) Измените DATABASE_NAME в своем классе "DatabaseHandler" (я столкнулся с такой же проблемой, но мне удалось сменить DATABASE_NAME.)

  • 0
    У меня есть своя собственная БД и использующий класс SQLiteAssetHelper. Итак, я создал сценарий БД с помощью sql, и БД была создана. Используя SQLiteAssetHelper, он не мог скопировать БД, пока не удалил приложение из эмулятора или устройства, потому что это была БД с той же версией.
4

Точки для запоминания при расширении SQLiteOpenHelper

  • super(context, DBName, null, DBversion); - Это должна быть вызвана первая строка конструктора
  • переопределить onCreate и onUpgrade (при необходимости)
  • onCreate будет вызываться только тогда, когда выполняется getWritableDatabase() или getReadableDatabase(). И это будет вызываться только один раз, когда DBName, указанный на первом шаге, недоступен. Вы можете добавить запрос create table в метод onCreate
  • Всякий раз, когда вы хотите добавить новую таблицу, просто измените DBversion и выполните запросы в таблице onUpgrade или просто удалите, затем установите приложение.
2

Вы можете создать базу данных и таблицу, например

public class DbHelper extends SQLiteOpenHelper {
private static final String DBNAME = "testdatbase.db";
private static final int VERSION = 1;

public DbHelper(Context context) {
    super(context, DBNAME, null, VERSION);
    // TODO Auto-generated constructor stub
}

@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub
    db.execSQL("create table BookDb(id integer primary key autoincrement,BookName text,Author text,IssuedOn text,DueDate text,Fine text,Totalfine text");

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS BookDb");
    onCreate(db);
  }
}

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

1

onCreate вызывается впервые, когда необходимо создание таблиц. Нам нужно переопределить этот метод, где мы пишем скрипт для создания таблицы, который выполняется SQLiteDatabase. метод execSQL. После выполнения при первом развертывании этот метод не будет вызываться далее.

onUpgrade Этот метод вызывается при обновлении версии базы данных. Предположим, что при первом развертывании версия базы данных была равна 1, а во втором развертывании произошли изменения в структуре базы данных, такие как добавление дополнительного столбца в таблицу. Предположим, что версия базы данных сейчас 2.

1

Если вы забыли указать строку "name" в качестве второго аргумента конструктору, она создаст базу данных "in-memory", которая будет стерта при закрытии приложения.

1

такая таблица не найдена, главным образом, когда вы не открыли класс SQLiteOpenHelper с getwritabledata(), и перед этим вам также нужно вызвать make constructor с именем базы данных и версией. И OnUpgrade вызывается всякий раз, когда есть значение обновления в номере версии, указанном в классе SQLiteOpenHelper.

Ниже приведен фрагмент кода (такой столбец не найден из-за заклинания в имени столбца):

public class database_db {
    entry_data endb;
    String file_name="Record.db";
    SQLiteDatabase sq;
    public database_db(Context c)
    {
        endb=new entry_data(c, file_name, null, 8);
    }
    public database_db open()
    {
        sq=endb.getWritableDatabase();
        return this;
    }
    public Cursor getdata(String table)
    {
        return sq.query(table, null, null, null, null, null, null);
    }
    public long insert_data(String table,ContentValues value)
    {
        return sq.insert(table, null, value);
    }
    public void close()
    {
        sq.close();
    }
    public void delete(String table)
    {
        sq.delete(table,null,null);
    }
}
class entry_data extends SQLiteOpenHelper
{

    public entry_data(Context context, String name, SQLiteDatabase.CursorFactory factory,
                      int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onCreate(SQLiteDatabase sqdb) {
        // TODO Auto-generated method stub

        sqdb.execSQL("CREATE TABLE IF NOT EXISTS 'YOUR_TABLE_NAME'(Column_1 text not null,Column_2 text not null);");

    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          onCreate(db);
    }

}
0

База данных Sqlite переопределяет два метода

1) onCreate(): этот метод вызывается только один раз, когда приложение запускается в первый раз. Так называется только один раз

2) onUpgrade() Этот метод вызывается, когда мы меняем версию базы данных, затем этот метод вызывается. Он используется для изменения структуры таблицы, например, для добавления нового столбца после создания схемы БД.

0

Повторно проверьте ваш запрос в классе DatabaseHandler/DatabaseManager (который вы когда-либо использовали)

0

Ваше имя базы данных должно заканчиваться на .db, также строки запроса должны иметь терминатор (;)

0

Удалите приложение из эмулятора или устройства. Запустите приложение еще раз. (OnCreate() не выполняется, когда база данных уже существует)

-3

Метод Sqliteopenhelper имеет методы создания и обновления, создание используется, когда каждая таблица создается впервые, и метод обновления будет вызываться каждый раз, когда изменяется номер таблицы столбца.

  • 0
    Метод onUpgrade вызывается при увеличении версии базы данных, а не при изменении номера столбца. Ссылка: developer.android.com/reference/android/database/sqlite/… , int, int)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню