【问题标题】:SQLite Problem: Program Crash When Try a QuerySQLite 问题:尝试查询时程序崩溃
【发布时间】:2011-02-20 21:10:04
【问题描述】:

我在使用 Android SDK 1.6 编程时遇到问题。我正在做与“记事本示例”相同的事情,但是当我尝试一些查询时程序崩溃了。如果我尝试直接在 DatabaseHelper create() 方法中进行查询,它会运行,但在这个函数之外它不会。你有什么想法吗?

这是来源:

public class DbAdapter {

    public static final String KEY_NAME = "name";
    public static final String KEY_TOT_DAYS = "totdays";
    public static final String KEY_ROWID = "_id";

    private static final String TAG = "DbAdapter";
    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;

    private static final String DATABASE_NAME = "flowratedb";
    private static final String DATABASE_TABLE = "girl_data";
    private static final String DATABASE_TABLE_2 = "girl_cyle";
    private static final int DATABASE_VERSION = 2;
    /**
     * Database creation sql statement
     */
    private static final String DATABASE_CREATE =
            "create table "+DATABASE_TABLE+" (id integer, name text not null, totdays int);";
    private static final String DATABASE_CREATE_2 =
        "create table "+DATABASE_TABLE_2+" (ref_id integer, day long not null);";

    private final Context mCtx;

    private static class DatabaseHelper extends SQLiteOpenHelper {

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

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE);
            db.execSQL(DATABASE_CREATE_2);
            db.delete(DATABASE_TABLE, null, null);
            db.delete(DATABASE_TABLE_2, null, null);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
            db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE_2);
            onCreate(db);
        }
    }
    public DbAdapter(Context ctx) {
        this.mCtx = ctx;
    }
    public DbAdapter open() throws SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }
    public void close() {
        mDbHelper.close();
    }
    public long createGirl(int id,String name, int totdays) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_ROWID, id);
        initialValues.put(KEY_NAME, name);
        initialValues.put(KEY_TOT_DAYS, totdays);
        return mDb.insert(DATABASE_TABLE, null, initialValues);
    }
    public long createGirl_fd_day(int refid, long fd) {
        ContentValues initialValues = new ContentValues();
        initialValues.put("ref_id", refid);
        initialValues.put("calendar", fd);
        return mDb.insert(DATABASE_TABLE, null, initialValues);
    }
    public boolean updateGirl(int rowId, String name, int totdays) {
        ContentValues args = new ContentValues();
        args.put(KEY_NAME, name);
        args.put(KEY_TOT_DAYS, totdays);

        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
    }
    public boolean deleteGirlsData() {
        if (mDb.delete(DATABASE_TABLE_2, null, null)>0)
            if(mDb.delete(DATABASE_TABLE, null, null)>0)
                return true;
        return false;
    }
    public Bundle fetchAllGirls() {
        Bundle extras = new Bundle();
        Cursor cur = mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_NAME,
                KEY_TOT_DAYS}, null, null, null, null, null);
        cur.moveToFirst();
        int tot = cur.getCount();
        extras.putInt("tot", tot);
        int index;
        for (int i=0;i<tot;i++){
            index=cur.getInt(cur.getColumnIndex("_id"));
            extras.putString("name"+index, cur.getString(cur.getColumnIndex("name")));
            extras.putInt("totdays"+index, cur.getInt(cur.getColumnIndex("totdays")));
        }
        cur.close();
        return extras;
    }
    public Cursor fetchGirl(int rowId) throws SQLException {

        Cursor mCursor =
                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
                        KEY_NAME, KEY_TOT_DAYS}, KEY_ROWID + "=" + rowId, null,
                        null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;

    }
    public Cursor fetchGirlCD(int rowId) throws SQLException {

        Cursor mCursor =
                mDb.query(true, DATABASE_TABLE_2, new String[] {"ref_id",
                        "day"}, "ref_id=" + rowId, null,
                        null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;

    }
}

【问题讨论】:

  • “程序崩溃”是什么意思?请包含您的 LogCat 输出。

标签: android database-connection


【解决方案1】:

我还没有机会测试我的理论,但看起来“DATABASE_CREATE”定义了“id”,而您正在查询中检索“_id”。您在顶部定义“KEY_ROWID”,但不要在数据库创建查询中使用该常量。

但是,如果这是您的主要问题,我不知道为什么“如果我尝试直接在 DatabaseHelper create() 方法中进行查询,它会运行,但在这个函数之外它不会”。

希望对您有所帮助。

【讨论】:

  • 我更正了 KEY_ROWID 定义,但问题仍然存在。注意:在 DatabaseHelper 的 onCreate() 方法中有删除(...),我让他们从那里尝试这个查询,他们不会崩溃,但在外面是的!
  • 同意,我也看到了使用 id 列的一些不一致之处(您使用“id”创建列,但使用“_id”获取并使用 KEY_ROWID 获取 fetchAllGirls() 中的值显然会失败,因为 _id 不在您的光标中)。我建议您对所有 PK id 列使用常量“BaseColumns._ID”。在您的创建语句中向该列添加 PK 约束,不要在创建时将其添加到 ContentValues,让 SQLite 为您自动生成。
  • 我解决了更改数据库的名称,可能是因为某些先例表。再见
【解决方案2】:

我遇到了同样的问题。即使在解决了所有问题后,查询仍然崩溃。

我更改了数据库名称,它开始工作了。

我怀疑,自从我测试出“坏”代码的早期迭代以来,我还没有重新启动我的模拟器,因此数据库的一个实例被卡在了其中一次运行中。

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,我通过查看您关于创建新数据库的评论解决了它。

    onCreate() 方法仅在创建数据库时调用。如果数据库已经创建(它会在您第一次尝试代码时创建:),下次运行模拟器时不会调用 onCreate。 因此在 onCreate() 方法中修改 sql 语句不会在下次启动模拟器时更改表,并且您仍然会拥有第一次启动模拟器并创建数据库时创建的表。在这种情况下,您的代码中将有错误的 sql 语句。 第二种情况是您使用了 adb-sqlite3 控制台(shell)程序并修改了表。数据库已经创建,因此不会调用 onCreate() - 无论您必须在 onCreate() 中描述表的代码是什么,该表都将与您通过 shell 修改它时相同...

    我的问题是我使用 shell 删除了表,并希望 onCreate 重新创建它们,但是数据库已经创建,并且没有表了。

    所以,结论是第一次创建DATABASE的时候所有的表都创建好了,如果需要修改,可以通过shell修改或者删除数据库,这样onCreate就会在你运行程序的时候调用.

    天哪,这段文字听起来像是一个无限循环:) 抱歉让答案复杂化了,我真的已经分层了...... :(

    祝你好运!

    【讨论】:

      【解决方案4】:

      一般来说,没有太多的错误处理。我可以在很多地方看到代码可能会崩溃。

      对于初学者,用 try-catch 包围这些东西

      • parseInt()
      • 执行查询、插入、更新,

      还有:

      • 在调用其 close() 方法之前,确保您的 mDB 变量不为空。
      • getcolumnIndex - 不使用这个,按你想要的顺序查询你的记录,然后你就会知道每个字段在什么索引。例如:SELECT id,name from table 然后你可以用 getString(1) 访问名称;

      最重要的是,熟悉adb logcat(下面的链接)。此工具将从您的设备中提取日志缓冲区并实时监控它以防崩溃。

      如果您的应用崩溃,adb+logcat 将向您显示堆栈跟踪,它将指向您的应用崩溃的确切行以及原因!

      https://developer.android.com/studio/command-line/adb.html#logcat

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多