我已经在我的SQLiteOpenHelper onCreate()中创建了我的表

SQLiteException: no such table

or

SQLiteException: no such column

错误。为什么?

注意: (这是每周数十个类似问题的汇总。试图在这里提供一个“规范的”社区wiki问题/答案,以便所有这些问题都可以指向一个很好的参考。)


当前回答

SQLiteOpenHelper onCreate()和onUpgrade()回调在数据库实际打开时被调用,例如通过调用getWritableDatabase()。在创建数据库帮助对象本身时,不会打开数据库。

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

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

onUpgrade()仅在数据库文件存在但存储的版本号低于构造函数中请求的版本号时调用。onUpgrade()应该将表模式更新到请求的版本。

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

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.name from the shell. Clear application data. Use the application manager. 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.

其他回答

没有这样的表,主要是当你没有打开SQLiteOpenHelper类与getwritabledata(),在此之前,你还必须调用make构造函数与databasename & version。 当SQLiteOpenHelper类中给出的版本号中有升级值时,OnUpgrade将被调用。

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

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

}

Sqlite数据库覆盖两种方法

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

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

在我的例子中,我从XML-file中获取带有<string-array>的项,其中存储<item>s。在这些<item>s我持有SQL字符串和应用databaseBuilder.addMigrations(迁移)一个接一个。我犯了一个错误,忘记在引用前添加\,得到了异常:

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>

SQLiteOpenHelper onCreate()和onUpgrade()回调在数据库实际打开时被调用,例如通过调用getWritableDatabase()。在创建数据库帮助对象本身时,不会打开数据库。

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

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

onUpgrade()仅在数据库文件存在但存储的版本号低于构造函数中请求的版本号时调用。onUpgrade()应该将表模式更新到请求的版本。

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

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.name from the shell. Clear application data. Use the application manager. 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.

根据Jaskey的要求,进一步补充这里的缺失点

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

Catch是构造函数

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

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

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

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

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

现在,假设您计划提供一个db version为3的应用程序的第三个版本(只有当数据库模式要修改时,db version才会增加)。在这种增量升级中,您必须从每个版本增量地编写升级逻辑,以获得更好的可维护代码

下面是伪代码示例:

@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的升级逻辑