Когда выполняется SQLiteOpenHelper onCreate() / onUpgrade ()?


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

SQLiteException: no such table

или

SQLiteException: no such column

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

Примечание:

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

13 252

13 ответов:

SQLiteOpenHelperonCreate() и onUpgrade() обратные вызовы вызываются, когда база данных фактически открыта, например, вызовом getWritableDatabase(). База данных не открывается при создании самого вспомогательного объекта базы данных.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ниже объяснение объясняет onUpgrade случае с примером.

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

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

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

@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

onCreate()

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

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

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

onUpgrade()

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

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

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

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

или

2) Установка -> приложения -> ClearData

или

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

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

или

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

что следует помнить при расширении SQLiteOpenHelper

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

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

такая таблица не найдена в основном, когда вы не открыли SQLiteOpenHelper класс getwritabledata() и перед этим вы также должны вызвать конструктор make с databasename & version. И 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);
    }

}

вы можете создать базу данных и таблицы, как

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);
  }
}

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

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

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

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

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

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

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