Android SQLiteOpenHelper onCreate() / onUpgrade() 何时运行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21881992/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:14:57  来源:igfitidea点击:

When is SQLiteOpenHelper onCreate() / onUpgrade() run?

androidsqliteandroid-sqlitesqlexceptionsqliteopenhelper

提问by laalto

I have created my tables in my SQLiteOpenHelperonCreate()but receive

我已经在我的表中创建了我的表,SQLiteOpenHelperonCreate()但收到

SQLiteException: no such table

or

或者

SQLiteException: no such column

errors. Why?

错误。为什么?

NOTE:

(This is the amalgamated summary of tens of similar questions every week. Attempting to provide a "canonical" community wiki question/answer here so that all those questions can be directed to a good reference.)

笔记:

(这是每周数十个类似问题的合并摘要。尝试在此处提供“规范”社区 wiki 问题/答案,以便所有这些问题都可以作为很好的参考。)

回答by laalto

SQLiteOpenHelperonCreate()and onUpgrade()callbacks are invoked when the database is actually opened, for example by a call to getWritableDatabase(). The database is not opened when the database helper object itself is created.

SQLiteOpenHelperonCreate()并且onUpgrade()在实际打开数据库时调用回调,例如通过调用getWritableDatabase(). 创建数据库助手对象本身时,不会打开数据库。

SQLiteOpenHelperversions the database files. The version number is the intargument passed to the constructor. In the database file, the version number is stored in PRAGMA user_version.

SQLiteOpenHelper版本数据库文件。版本号是int传递给构造函数的参数。在数据库文件中,版本号存储在PRAGMA user_version.

onCreate()is only run when the database file did not exist and was just created. If onCreate()returns successfully (doesn't throw an exception), the database is assumed to be created with the requested version number. As an implication, you should not catch SQLExceptions in onCreate()yourself.

onCreate()仅在数据库文件不存在且刚刚创建时运行。如果onCreate()成功返回(不抛出异常),则假定数据库是使用请求的版本号创建的。作为暗示,您不应该SQLExceptiononCreate()自己身上捕获s 。

onUpgrade()is only called when the database file exists but the stored version number is lower than requested in the constructor. The onUpgrade()should update the table schema to the requested version.

onUpgrade()仅当数据库文件存在但存储的版本号低于构造函数中请求的版本号时才调用。本onUpgrade()应更新表架构所需的版本。

When changing the table schema in code (onCreate()), you should make sure the database is updated. Two main approaches:

在代码 ( onCreate()) 中更改表架构时,应确保数据库已更新。两种主要方法:

  1. Delete the old database file so that onCreate()is run again. This is often preferred at development time where you have control over the installed versions and data loss is not an issue. Some ways to delete the database file:

    • Uninstall the application. Use the application manager or adb uninstall your.package.namefrom the shell.

    • Clear application data. Use the application manager.

  2. Increment the database version so that onUpgrade()is invoked. This is slightly more complicated as more code is needed.

    • For development time schema upgrades where data loss is not an issue, you can just use execSQL("DROP TABLE IF EXISTS <tablename>")in to remove your existing tables and call onCreate()to recreate the database.

    • For released versions, you should implement data migration in onUpgrade()so your users don't lose their data.

  1. 删除旧的数据库文件,以便onCreate()再次运行。这在开发时通常是首选,您可以控制已安装的版本并且数据丢失不是问题。删除数据库文件的一些方法:

    • 卸载应用程序。使用应用程序管理器或adb uninstall your.package.name从 shell。

    • 清除应用程序数据。使用应用程序管理器。

  2. 增加数据库版本以便onUpgrade()调用。由于需要更多代码,这稍微复杂一些。

    • 对于数据丢失不是问题的开发时间架构升级,您可以使用execSQL("DROP TABLE IF EXISTS <tablename>")in 删除现有表并调用onCreate()以重新创建数据库。

    • 对于已发布的版本,您应该实现数据迁移,onUpgrade()这样您的用户就不会丢失他们的数据。

回答by Aun

To further add missing points here, as per the request by Jaskey

根据 Jaskey 的要求,在此处进一步添加缺失的点

Database version is stored within the SQLitedatabase file.

数据库版本存储在SQLite数据库文件中。

catch is the constructor

catch 是构造函数

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

So when the database helper constructor is called with a name(2nd param), platform checks if the database exists or not and if the database exists, it gets the version information from the database file header and triggers the right call back

因此,当使用name(第二个参数)调用数据库助手构造函数时,平台检查数据库是否存在,如果数据库存在,它从数据库文件头中获取版本信息并触发正确的回调

As already explained in the older answer, if the database with the name doesn't exists, it triggers onCreate.

正如旧答案中已经解释的那样,如果具有该名称的数据库不存在,则会触发onCreate.

Below explanation explains onUpgradecase with an example.

下面的解释onUpgrade以一个例子来解释情况。

Say, your first version of application had the DatabaseHelper(extending SQLiteOpenHelper) with constructor passing version as 1and then you provided an upgraded application with the new source code having version passed as 2, then automatically when the DatabaseHelperis constructed, platform triggers onUpgradeby seeing the file already exists, but the version is lower than the current version which you have passed.

说,你的第一个版本的应用程序有DatabaseHelper(扩展SQLiteOpenHelper)和构造函数传递版本1,然后你提供了一个升级的应用程序,新源代码的版本传递为2,然后在DatabaseHelper构建时自动,平台onUpgrade通过看到文件已经存在而触发,但版本低于您通过的当前版本。

Now say you are planing to give a third version of application with db version as 3(db version is increased only when database schema is to be modified). In such incremental upgrades, you have to write the upgrade logic from each version incrementally for a better maintainable code

现在假设您打算提供具有 db 版本的第三个版本的应用程序3(仅在修改数据库架构时才会增加 db 版本)。在这种增量升级中,您必须从每个版本增量地编写升级逻辑以获得更好的可维护代码

Example pseudo code below:

示例伪代码如下:

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

Notice the missing breakstatement in case 1and 2. This is what I mean by incremental upgrade.

注意breakcase1和 中缺少的语句2。这就是我所说的增量升级的意思。

Say if the old version is 2and new version is 4, then the logic will upgrade the database from 2to 3and then to 4

假设旧版本是2新版本4,那么逻辑将数据库从 升级23,然后升级到4

If old version is 3and new version is 4, it will just run the upgrade logic for 3to 4

如果旧版本3和新版本4,它只是运行升级的逻辑34

回答by jeet parmar

onCreate()

onCreate()

  1. When we create DataBase at a first time (i.e Database is not exists) onCreate()create database with version which is passed in SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

  2. onCreate()method is creating the tables you've defined and executing any other code you've written. However, this method will only be called if the SQLite file is missing in your app's data directory (/data/data/your.apps.classpath/databases).

  3. This method will not be called if you've changed your code and relaunched in the emulator. If you want onCreate()to run you need to use adb to delete the SQLite database file.

  1. 当我们第一次创建数据库时(即数据库不存在)onCreate()用传入的版本创建数据库 SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

  2. onCreate()方法是创建您定义的表并执行您编写的任何其他代码。但是,只有在应用程序的数据目录 ( /data/data/your.apps.classpath/databases) 中缺少 SQLite 文件时,才会调用此方法。

  3. 如果您更改了代码并在模拟器中重新启动,则不会调用此方法。如果要onCreate()运行则需要使用 adb 删除 SQLite 数据库文件。

onUpgrade()

onUpgrade()

  1. SQLiteOpenHelpershould call the super constructor.
  2. The onUpgrade()method will only be called when the version integer is larger than the current version running in the app.
  3. If you want the onUpgrade()method to be called, you need to increment the version number in your code.
  1. SQLiteOpenHelper应该调用超级构造函数。
  2. onUpgrade()仅当版本整数大于应用程序中运行的当前版本时才会调用该方法。
  3. 如果要onUpgrade()调用该方法,则需要增加代码中的版本号。

回答by Kush

May be I am too late but I would like to share my short and sweet answer. Please check Answerfor a same problem. It will definitely help you. No more deep specifications.

可能是我太晚了,但我想分享我简短而甜蜜的答案。请检查答案以获取相同的问题。它肯定会帮助你。没有更深的规格。

If you are confident about syntax for creating table, than it may happen when you add new column in your same table, for that...

如果您对创建表的语法有信心,那么在同一个表中添加新列时可能会发生这种情况,为此...

1) Uninstall from your device and run it again.

1) 从您的设备中卸载并再次运行。

OR

或者

2) Setting -> app -> ClearData

2) 设置 -> 应用程序 -> ClearData

OR

或者

3)Change DATABASE_VERSIONin your "DatabaseHandler" class (If you have added new column than it will upgrade automatically)

3)更改DATABASE_VERSION您的“DatabaseHandler”类(如果您添加了新列,它将自动升级)

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

OR

或者

4)Change DATABASE_NAMEin your "DatabaseHandler" class (I faced same problem. But I succeed by changing DATABASE_NAME.)

4)更改DATABASE_NAME您的“DatabaseHandler”类(我遇到了同样的问题。但我通过更改成功了DATABASE_NAME。)

回答by JibinNajeeb

Points to remember when extending SQLiteOpenHelper

延长时要记住的要点 SQLiteOpenHelper

  1. super(context, DBName, null, DBversion);- This should be invoked first line of constructor
  2. override onCreateand onUpgrade(if needed)
  3. onCreatewill be invoked only when getWritableDatabase()or getReadableDatabase()is executed. And this will only invoked once when a DBNamespecified in the first step is not available. You can add create table query on onCreatemethod
  4. Whenever you want to add new table just change DBversionand do the queries in onUpgradetable or simply uninstall then install the app.
  1. super(context, DBName, null, DBversion);- 这应该在构造函数的第一行调用
  2. 覆盖onCreateonUpgrade(如果需要)
  3. onCreate只会在getWritableDatabase()getReadableDatabase()被执行时被调用。这只会DBName在第一步中指定的a不可用时调用一次。您可以在onCreate方法上添加创建表查询
  4. 每当您想添加新表时,只需更改DBversion并在onUpgrade表中执行查询或简单地卸载然后安装该应用程序。

回答by Faxriddin Abdullayev

onCreateis called for the first time when creation of tables are needed. We need to override this method where we write the script for table creation which is executed by SQLiteDatabase. execSQL method. After executing in first time deployment, this method will not be called onwards.

当需要创建表时第一次调用onCreate。我们需要重写这个方法,在那里我们编写由 SQLiteDatabase 执行的表创建脚本。execSQL 方法。在第一次部署时执行后,此方法将不会被调用。

onUpgradeThis method is called when database version is upgraded. Suppose for the first time deployment , database version was 1 and in second deployment there was change in database structure like adding extra column in table. Suppose database version is 2 now.

onUpgrade数据库版本升级时调用此方法。假设第一次部署,数据库版本为 1,在第二次部署中,数据库结构发生了变化,比如在表中添加了额外的列。假设现在数据库版本是 2。

回答by sushant suryawanshi

Sqlite database override two methods

Sqlite 数据库重写两种方法

1) onCreate(): This method invoked only once when the application is start at first time . So it called only once

1) onCreate():该方法仅在应用程序第一次启动时调用一次。所以它只调用了一次

2)onUpgrade() This method called when we change the database version,then this methods gets invoked.It is used for the alter the table structure like adding new column after creating DB Schema

2)onUpgrade() 当我们改变数据库版本时调用这个方法,然后这个方法被调用。它用于改变表结构,如创建DB Schema后添加新列

回答by Enamul Haque

You can create database & table like

您可以创建数据库和表

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

Note : if you want create another table or add columns or no such table, just increment the VERSION

注意:如果你想创建另一个表或添加列或没有这样的表,只需增加 VERSION

回答by phreakhead

If you forget to provide a "name" string as the second argument to the constructor, it creates an "in-memory" database which gets erased when you close the app.

如果您忘记提供“名称”字符串作为构造函数的第二个参数,它会创建一个“内存中”数据库,当您关闭应用程序时该数据库将被删除。

回答by Bharat Lalwani

no such table found is mainly when you have not opened the SQLiteOpenHelperclass with getwritabledata()and before this you also have to call make constructor with databasename & version. And OnUpgradeis called whenever there is upgrade value in version number given in SQLiteOpenHelperclass.

找不到这样的表主要是当您没有打开SQLiteOpenHelper类时getwritabledata(),在此之前您还必须使用数据库名称和版本调用 make 构造函数。并且OnUpgradeSQLiteOpenHelper类中给出的版本号中有升级值时调用。

Below is the code snippet (No such column found may be because of spell in column name):

下面是代码片段(没有找到这样的列可能是因为列名中的拼写):

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

}