Android SQLiteException:表已存在(代码1)

Android SQLiteException:表已存在(代码1),android,exception,android-sqlite,oncreate,Android,Exception,Android Sqlite,Oncreate,最终编辑,问题“已解决” 因此,根据接受的答案,我最终删除了将数据库版本作为参数的构造函数,但这仍然导致了异常。正如我所建议的,我添加了一个try{}catch{}block来捕获这个问题,我告诉你,它仍然显示抛出异常,只是这次它没有使应用程序崩溃。幸运的是,尽管它在创建数据库时似乎有问题,但它允许我将db内容加载到应用程序中,因此我现在对日志消息没有意见:) 以下是onCreate: @Override public void onCreate(SQLiteDatabase db) {

最终编辑,问题“已解决”

因此,根据接受的答案,我最终删除了将数据库版本作为参数的构造函数,但这仍然导致了异常。正如我所建议的,我添加了一个
try{}catch{}
block来捕获这个问题,我告诉你,它仍然显示抛出异常,只是这次它没有使应用程序崩溃。幸运的是,尽管它在创建数据库时似乎有问题,但它允许我将db内容加载到应用程序中,因此我现在对日志消息没有意见:)

以下是onCreate:

@Override
public void onCreate(SQLiteDatabase db) {
    Constants.logMessage("Creating database from scratch?");
    //Create both of the tables as part of the databases
    try {
        db.execSQL(CREATE_TABLE_COUNTRIES);
        db.execSQL(CREATE_TABLE_REGIONS);
        db.execSQL(CREATE_TABLE_CITIES);
    }
    catch (Exception e) {
        //This happens on every launch that isn't the first one. 
        Log.w("SpotTheStation", "Error while creating db: " + e.toString());
    }       
}

我在android应用程序上使用SQLite,似乎遇到了一个非常奇怪的问题。似乎每次我调用
getWriteableDatabase()
时,系统都会尝试重新创建整个数据库,即调用
onCreate()
,这会导致SQLiteException

以下是完整的错误消息:

03-21 14:36:44.082: V/SpotTheStation(20034): android.database.sqlite.SQLiteException:, 
while compiling: create table countries(_id integer primary key autoincrement,
country text);
每次我尝试访问DBdata时都会发生这种情况,我有一个单独的静态类在整个应用生命周期中处理DB访问,我通过以下方式将上下文传递给它:

public static Cursor getCountries (final Context context) {

    if (mDatabase == null || !mDatabase.isOpen()) {
        Constants.logMessage("DB was null, opening");
        open(context);
    }

    return mDatabase.query(CountryDbHelper.TABLE_COUNTRIES, CountryDbHelper.PROJECTION_COUNTRIES, null, null, null, null, CountryDbHelper.DEFAULT_SORT_ORDER);          
}
每次我调用这个方法时,日志都会声明实际上正在打开数据库,这很好。以下是我打开数据库的方式:

private static void open (Context context) {
    if (mDatabase != null && mDatabase.isOpen()) {
        return;
    }
    try {
        mHelper = new CountryDbHelper(context);
        mDatabase = mHelper.getWritableDatabase();
    } catch (Exception e) {
        Constants.logMessage(e.toString());
    }
}
这就是导致异常的语句,因为getWriteableDatabase应该有一个缓存数据库,或者应该调用
onOpen()
,而不是
onCreate()

下面是create语句,它似乎在每次db访问调用时都会执行:

private static final String DATABASE_CREATE = "create table " + TABLE_COUNTRIES 
        + "(_id integer primary key autoincrement, " 
        + "country text);"
        ;
下面是非常简单的
onCreate()

@Override
public void onCreate(SQLiteDatabase db) {
    Constants.logMessage("Creating database from scratch?");
    db.execSQL(DATABASE_CREATE);
}
我添加了日志消息以跟踪问题,以下是进展:

03-21 14:36:44.004: V/SpotTheStation(20034): DB was null, opening
03-21 14:36:44.035: V/SpotTheStation(20034): Creating database from scratch?
03-21 14:36:44.082: V/SpotTheStation(20034): android.database.sqlite.SQLiteException: table countries already exists (code 1): , while compiling: create table countries(_id integer primary key autoincrement, country text);
现在,让我困扰的是,我在其他几个应用程序上使用了相同的DB结构(相同的逻辑、一个非静态OpenHelper和一个访问DB内容的静态管理器),并且一切正常,不确定是什么导致了这里的问题

我非常感谢你的帮助

快速编辑

为了更清楚一点,在第一次启动(应用程序第一次运行)时,
getCountries
确实起作用,后续运行将导致异常。卸载-重新安装过程使其再次工作,然后在第二次运行时停止

编辑第二条

根据请求,以下是OpenHelper的完整代码:

public class CountryDbHelper extends SQLiteOpenHelper {

/**
 * This path is hardcoded, during the first time application opens
 * we copy a database file from the assets folder into this folder. 
 */
public final static String DB_PATH = "/data/data/com.nasa.apps.spotthestation/databases/";
private static final int DB_VERSION = 2;
public static String DB_NAME = "countries";
public static final String TABLE_COUNTRIES = "countries";
public static final String TABLE_REGIONS = "regions";
public static final String DEFAULT_SORT_ORDER = "_id";
public static final String [] PROJECTION_COUNTRIES = {
    "_id",
    "country"
};

public static final String [] PROJECTION_REGIONS = {
    "_id",
    "country",
    "region"
};

/**
 * Table with only countries
 */
private static final String CREATE_TABLE_COUNTRIES = "create table " + TABLE_COUNTRIES 
        + "(_id integer primary key autoincrement, " 
        + "country text);"
        ;

/**
 * Table that contains regions per country
 */
private static final String CREATE_TABLE_REGIONS = "create table " + TABLE_REGIONS 
        + "(_id integer primary key autoincrement, " 
        + "country text, "
        + "region text);"
        ;

/**
 * Not used for now
 */
private static final String CREATE_TABLE_CITIES = "create table " + TABLE_COUNTRIES 
        + "(_id integer primary key autoincrement, " 
        + "country text, "
        + "region text, "
        + "city text);"
        ;

public CountryDbHelper(Context context, CursorFactory factory,
        int version) {
    super(context, DB_NAME, factory, version);
}

public CountryDbHelper (Context context) {
    super(context, DB_NAME, null, DB_VERSION );
}

@Override
public void onCreate(SQLiteDatabase db) {
    Constants.logMessage("Creating database from scratch?");
    //Create both of the tables as part of the databases
    db.execSQL(CREATE_TABLE_COUNTRIES);
    db.execSQL(CREATE_TABLE_REGIONS);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    Constants.logMessage("Upgrading db from " + oldVersion + " to new version: " + newVersion);
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_COUNTRIES);
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_REGIONS);
    onCreate(db);
}
}
另外,我注意到,/data/data/packageName/databases/上的数据库文件没有“sqlite_序列”文件,该文件通常存储数据库中每个表的行数。我认为问题可能是文件丢失,因为这两个表使用“主键自动增量”,我相信它依赖于这一点来知道插入时要使用的下一个id。有人能证实这一点吗

再次编辑以防万一,我继续将“_id”字段上的数据类型从
autoincrement
更改为简单的
numeric
,因为我不打算向数据库添加更多数据,这是只读的,但在第二次启动时仍然强制关闭


谢谢

是否在类构造函数中添加此
super(上下文、数据库名称、null、数据库版本)


我经历过这个问题,在DROP TABLE行的末尾添加一个解决了我的问题

db.execSQL("DROP TABLE IF EXISTS " + TABLE_COUNTRIES + ";");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_REGIONS + ";");

请不要忘记在需要时更改版本。

请注意,数据库已经存在,并且有数据。您是在模拟器上还是在真实手机上运行该应用程序?Galaxy Nexus就是这样。您能提供完整的SQLiteOpenHelper实现吗?添加了完整的Helper实现。我不确定您的意思,抱歉。但是如果你的问题是我是否在使用你发布的构造函数,那么是的,检查问题的更新代码。您确定您从未调用过将“version”作为参数的构造函数吗?我建议彻底摆脱那个构造器。。。或者至少让它私有化我自己不这么认为,我只使用一个有“上下文”的参数作为参数。我会在回家后删除额外的构造函数,但是你能详细说明一下为什么这个构造函数会引起问题吗?
db.execSQL("DROP TABLE IF EXISTS " + TABLE_COUNTRIES + ";");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_REGIONS + ";");