什么时候SQLiteOpenHelper的onCreate()/ onUpgrade()运行?
我在我的SQLiteOpenHelper onCreate()创build我的表,但收到 
 SQLiteException: no such table 
要么
 SQLiteException: no such column 
错误。 为什么?
注意:
(这是每周几十个类似问题的汇总总结,试图在这里提供一个“规范的”社区wiki问题/答案,以便所有这些问题都可以被引导到一个很好的参考)。
 实际打开数据库时调用SQLiteOpenHelper onCreate()和onUpgrade()callback,例如调用getWritableDatabase() 。 创build数据库帮助程序对象时,数据库不会打开。 
  SQLiteOpenHelper版本的数据库文件。 版本号是传递给构造函数的int参数。 在数据库文件中,版本号存储在PRAGMA user_version 。 
  onCreate()只在数据库文件不存在并刚刚创build时才运行。 如果onCreate()成功返回(不抛出exception),则假定数据库使用所请求的版本号创build。 作为暗示,您不应该在onCreate()捕获SQLException 。 
  onUpgrade()只在数据库文件存在时才被调用,但存储的版本号低于构造函数中的要求。  onUpgrade()应该将表模式更新为所请求的版本。 
 在代码( onCreate() )中更改表架构时,应确保数据库已更新。 两个主要方法: 
- 
删除旧的数据库文件,以便再次运行 onCreate()。 在开发时,这通常是首选,您可以控制安装的版本,数据丢失不是问题。 一些方法来删除数据库文件:- 
卸载应用程序。 使用应用程序pipe理器或 adb uninstall your.package.name从shell中adb uninstall your.package.name。
- 
清除应用程序数据 使用应用程序pipe理器。 
 
- 
- 
增加数据库版本,以便调用 onUpgrade()。 随着需要更多的代码,这会稍微复杂一些。- 
对于数据丢失不是问题的开发时间模式升级,可以使用 execSQL("DROP TABLE IF EXISTS <tablename>")来删除现有表并调用onCreate()来重新创build数据库。
- 
对于发布的版本,您应该在 onUpgrade()实现数据迁移,以便您的用户不会丢失数据。
 
- 
根据Jaskey的要求,在这里进一步增加缺失点
  数据库版本存储在SQLite数据库文件中。 
catch是构造函数
 SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) 
 因此,当数据库帮助器构造函数被调用name (第二参数)时,平台会检查数据库是否存在,如果数据库存在,它将从数据库文件头获取版本信息并触发正确的callback 
 正如前面已经解释过的,如果名称不存在的数据库,它会触发onCreate 。 
 下面以一个例子来说明onUpgrade情况。 
 假设你的第一个版本的应用程序有DatabaseHelper (扩展SQLiteOpenHelper ),其构造函数传递版本为1 ,然后你提供了一个升级的应用程序,新的源代码的版本传递为2 ,然后当DatabaseHelper被构造时,平台自动触发onUpgrade看到文件已经存在,但版本低于您已经传递的当前版本。 
 现在说你打算给数据库版本为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); } } 
 注意情况1和2的缺失break声明。 这就是我所说的增量升级。 
 说如果旧版本是2 ,新版本是4 ,那么逻辑将数据库从2升级到3 ,然后升级到4 
 如果旧版本为3 ,新版本为4 ,则只运行升级逻辑3至4 
 onCreate() 
- 
当我们第一次创build数据库(即数据库不存在) onCreate()创build数据库与SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)传递的SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
- 
onCreate()方法创build您定义的表并执行您编写的任何其他代码。 但是,只有在应用程序数据目录中缺lessSQLite文件(/data/data/your.apps.classpath/databases)时才会调用此方法。
- 
如果您更改了代码并在模拟器中重新启动,则不会调用此方法。 如果你想运行 onCreate(),你需要使用adb来删除SQLite数据库文件。
 onUpgrade() 
-   SQLiteOpenHelper应该调用超级构造函数。
-   onUpgrade()方法只会在版本的整数大于应用中运行的当前版本时被调用。
-  如果要调用onUpgrade()方法,则需要在代码中增加版本号。
可能是我太晚了,但我想分享我简短而甜蜜的回答。 请检查答案是否有同样的问题。 这一定会帮助你。 没有更深的规格。
如果您对创build表的语法有信心,那么当您在同一个表中添加新列时,可能会发生这种情况。
1)从您的设备卸载并再次运行。
要么
2)设置 – >应用程序 – > ClearData
要么
  3)在你的“DatabaseHandler”类中更改DATABASE_VERSION (如果你添加了新的列而不是自动升级) 
 public DatabaseHandler(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } 
要么
  4)改变你的“DatabaseHandler”类中的DATABASE_NAME (我面临同样的问题,但是我通过改变DATABASE_NAME成功)。 
 在扩展SQLiteOpenHelper时要记住的SQLiteOpenHelper 
-  super(context, DBName, null, DBversion);– 这应该被调用构造函数的第一行
-  重写onCreate和onUpgrade(如果需要)
-  只有在执行getWritableDatabase()或getReadableDatabase()时,才会调用onCreate。 这只会在第一步指定的DBName不可用时调用一次。 您可以在onCreate方法上添加创build表查询
-  每当你想添加新表,只需更改DBversion并在onUpgrade表中执行查询,或者只需卸载然后安装应用程序。
你可以像创build数据库和表
 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); } } 
注意:如果你想创build另一个表或添加列或没有这样的表,只需增加VERSION
从模拟器或设备上卸载您的应用程序。 再次运行应用程序。 (当数据库已经存在时,OnCreate()不会被执行)
 没有find这样的表主要是当你没有打开与getwritabledata()的SQLiteOpenHelper类之前,你还必须调用与数据库名称和版本的构造函数。 并且在SQLiteOpenHelper类中给定的版本号中有升级值时调用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); } } 
如果您忘记提供一个“名称”string作为构造函数的第二个参数,它会创build一个“内存”数据库,当您closures该应用程序时将被删除。
您的数据库名称必须以.db结尾,您的查询string也必须有一个终止符(;)
Sqliteopenhelper的方法有方法创build和升级,创build时使用,当任何表第一次创build和升级方法将调用每当表的列号改变。