我已在SQLiteOpenHelper
onCreate()
创建了我的表格,但收到了
SQLiteException: no such table
或
SQLiteException: no such column
错误。为什么呢?
注意:
(这是每周数十个类似问题的合并摘要。试图在这里提供一个“规范的”社区维基问题/答案,以便所有这些问题可以直接提供给参考。)
答案 0 :(得分:342)
SQLiteOpenHelper
onCreate()
和onUpgrade()
回调,例如通过调用getWritableDatabase()
。创建数据库帮助程序对象本身时,不会打开数据库。
SQLiteOpenHelper
版本的数据库文件。版本号是传递给constructor的int
参数。在数据库文件中,版本号存储在PRAGMA user_version
。
onCreate()
仅在数据库文件不存在且刚刚创建时运行。如果onCreate()
成功返回(不抛出异常),则假定使用请求的版本号创建数据库。这意味着,您不应该自己在SQLException
中抓住onCreate()
。
onUpgrade()
仅在数据库文件存在时调用,但存储的版本号低于构造函数中请求的版本号。 onUpgrade()
应将表架构更新为请求的版本。
在代码(onCreate()
)中更改表模式时,应确保更新数据库。两种主要方法:
删除旧数据库文件,以便再次运行onCreate()
。在开发时,您通常首选这种方法,您可以控制已安装的版本,并且数据丢失不是问题。删除数据库文件的一些方法:
卸载应用程序。使用应用程序管理器或shell中的adb uninstall your.package.name
。
清除申请数据。使用应用程序管理器。
增加数据库版本,以便调用onUpgrade()
。由于需要更多代码,因此稍微复杂一些。
对于数据丢失不成问题的开发时架构升级,您只需使用execSQL("DROP TABLE IF EXISTS <tablename>")
删除现有表并调用onCreate()
即可重新创建数据库。
对于已发布的版本,您应该在onUpgrade()
中实施数据迁移,这样您的用户就不会丢失数据。
答案 1 :(得分:95)
根据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
答案 2 :(得分:20)
<强> onCreate()
强>
当我们第一次创建DataBase时(即数据库不存在)onCreate()
使用传入的版本创建数据库
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
onCreate()
方法正在创建您定义的表并执行您编写的任何其他代码。但是,只有在应用程序的数据目录(/data/data/your.apps.classpath/databases
)中缺少SQLite文件时,才会调用此方法。
如果您更改了代码并在模拟器中重新启动,则不会调用此方法。如果您希望onCreate()
运行,则需要使用adb删除SQLite数据库文件。
<强> onUpgrade()
强>
SQLiteOpenHelper
应该调用超级构造函数。onUpgrade()
方法。onUpgrade()
方法,则需要增加代码中的版本号。答案 3 :(得分:9)
可能是我来不及但是我想分享我简短而又甜蜜的答案。 请检查Answer是否存在同样的问题。它一定会帮到你。没有更深入的规范。
如果您对创建表的语法有信心,那么当您在同一个表中添加新列时,可能会发生这种情况......
1)从您的设备上卸载并重新运行。
OR
2)设置 - &gt; app - &gt; ClearData 强>
OR
3)在&#34; DatabaseHandler&#34;中更改DATABASE_VERSION
class(如果添加了新列,则会自动升级)
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
OR
4)在&#34; DatabaseHandler&#34;中更改DATABASE_NAME
上课(我遇到了同样的问题。但我通过改变DATABASE_NAME
来取得成功。)
答案 4 :(得分:4)
延长SQLiteOpenHelper
super(context, DBName, null, DBversion);
- 应该在构造函数的第一行调用onCreate
和onUpgrade
(如果需要)onCreate
或getWritableDatabase()
时才会调用getReadableDatabase()
。这只会在第一步中指定的DBName
不可用时调用一次。您可以在onCreate
方法DBversion
并在onUpgrade
表中执行查询,或者只需卸载然后再安装该应用。答案 5 :(得分:2)
您可以创建数据库&amp;表格如
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
答案 6 :(得分:2)
onCreate 。我们需要覆盖这个方法,我们编写由SQLiteDatabase执行的表创建脚本。 execSQL方法。在第一次部署中执行后,此方法将不会被调用。
<强> onUpgrade 强> 升级数据库版本时调用此方法。假设第一次部署,数据库版本为1,在第二次部署中,数据库结构发生了变化,如在表中添加额外列。假设数据库版本现在为2。
答案 7 :(得分:1)
找不到这样的表主要是因为你没有用SQLiteOpenHelper
打开getwritabledata()
类,在此之前你还必须调用带有databasename&amp;的make构造函数。版。
只要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);
}
}
答案 8 :(得分:1)
如果您忘记提供姓名&#34; string作为构造函数的第二个参数,它创建了一个&#34; in-memory&#34;关闭应用程序时会删除的数据库。
答案 9 :(得分:0)
从模拟器或设备卸载您的应用程序。再次运行该应用程序。 (当数据库已存在时,不执行OnCreate())
答案 10 :(得分:0)
您的数据库名称必须以.db结尾,您的查询字符串也必须有终结符(;)
答案 11 :(得分:0)
在您的DatabaseHandler / DatabaseManager类中重新检查您的查询(无论您用过什么)
答案 12 :(得分:0)
Sqlite数据库覆盖两种方法
1)onCreate(): 首次启动应用程序时,仅调用一次此方法。因此它只调用了一次
2)onUpgrade() 更改数据库版本时调用此方法,然后调用此方法。该方法用于更改表结构,例如在创建数据库模式后添加新列
答案 13 :(得分:0)
在我的情况下,我使用<string-array>
从XML文件中获取项目,我在其中存储了<item>
。在这些<item>
中,我持有SQL字符串,并与databaseBuilder.addMigrations(migration)
一一对应。我犯了一个错误,忘记在引号前添加\
并得到了例外:
android.database.sqlite.SQLiteException:无此类列:some_value(代码1 SQLITE_ERROR):,而在编译时:INSERT INTO table_name(id,name)VALUES(1,some_value)
因此,这是正确的变体:
<item>
INSERT INTO table_name(id, name) VALUES(1, \"some_value\")
</item>
答案 14 :(得分:-2)
Sqliteopenhelper的方法有方法创建和升级,在第一次创建任何表时使用create,每当表的列数改变时,都会调用upgrade方法。