db.query无法使用整数字段进行选择

时间:2019-07-02 02:17:33

标签: java android sqlite

我有一个包含2个表的数据库-类别和任务,每个任务都有一个与类别_id字段关联的字段。问题是在task.category_id =当前类别ID上的选择返回空游标。

在调试模式下可以看到选择标准是正确的;检查数据库字段并具有正确的值;删除选择标准将正确返回完整的数据库。 如果在第一个参数中进行了所有选择,则将.query替换为.rawQuery会返回正确的值。这个很好用:

  String selection = "select * from task where category_id = " + mId;
  Cursor taskCursor = mDb.rawQuery(selection, null);

MainActivity:

 //request data from categories table
    mDb = mDbOpenHelper.getReadableDatabase();
    final Cursor categoryCursor = mDb.query(CategoryEntry.TABLE_NAME, 
        null,null, null, null, null, null);

    int mCategoryIdPos = mCursor.getColumnIndex(CategoryEntry._ID);
    int mId = mCursor.getInt(mCategoryIdPos);
 //request data from tasks table for the selected category
    String selection = TaskEntry.COLUMN_CATEGORY_ID + " = ?";
    String selectionArgs = Integer.toString(mId);
    Cursor taskCursor = mDb.query(TaskEntry.TABLE_NAME, null, selection, 
        selectionArgs, null, null, null, null)

taskCursor为空。

DatabaseContractClass:

    public static final class TaskEntry implements BaseColumns {
    public static final String TABLE_NAME = "task";
    public static final String COLUMN_TASK_NAME = "task_name";
    public static final String COLUMN_CATEGORY_ID = "category_id";
    public static final String COLUMN_SKILL_ID = "skill_id";
    public static final String COLUMN_TASK_PD = "task_pd";
    public static final String COLUMN_TASK_DATE = "task_date";
    public static final String COLUMN_TASK_PERIOD = "task_period";
    public static final String COLUMN_TASK_FREQUENCY = "task_frequency";
    public static final String COLUMN_TASK_ONBY = "task_onby";
    public static final String COLUMN_TASK_COMPLETION = 
      "task_completion";

    public static final String SQL_CREATE_TABLE = "CREATE TABLE " + 
         TABLE_NAME + " (" +
            _ID + " INTEGER PRIMARY KEY, " +
            COLUMN_TASK_NAME + " TEXT UNIQUE NOT NULL, " +
            COLUMN_CATEGORY_ID + ", " +
            COLUMN_SKILL_ID + ", " +
            COLUMN_TASK_PD + ", " +
            COLUMN_TASK_DATE + ", " +
            COLUMN_TASK_PERIOD + ", " +
            COLUMN_TASK_FREQUENCY + ", " +
            COLUMN_TASK_ONBY + ", " +
            COLUMN_TASK_COMPLETION + ")";
}

public static final class CategoryEntry implements BaseColumns{
    public static final String TABLE_NAME = "category";
    public static final String COLUMN_CATEGORY_NAME = "category_name";
    public static final String COLUMN_CATEGORY_PD = "category_pd";
    public static final String COLUMN_CATEGORY_DATE = "category_date";
    public static final String COLUMN_CATEGORY_PERIOD = 
   "category_period";
    public static final String COLUMN_CATEGORY_FREQUENCY = 
     "category_frequency";
    public static final String COLUMN_CATEGORY_ONBY = "category_onby";
    public static final String COLUMN_CATEGORY_COMPLETION = 
       "category_completion";

    public static final String SQL_CREATE_TABLE = "CREATE TABLE " + enter 
      code hereTABLE_NAME + " (" +
            _ID + " INTEGER PRIMARY KEY, " +
            COLUMN_CATEGORY_NAME + " TEXT UNIQUE NOT NULL, " +
            COLUMN_CATEGORY_PD + ", " +
            COLUMN_CATEGORY_DATE + ", " +
            COLUMN_CATEGORY_PERIOD + ", " +
            COLUMN_CATEGORY_FREQUENCY + ", " +
            COLUMN_CATEGORY_ONBY + ", " +
            COLUMN_CATEGORY_COMPLETION + ")";
}

1 个答案:

答案 0 :(得分:1)

您似乎有一些问题。

问题1

选择参数args,query的第4个参数,应该是String[]而不是String

public Cursor query (String table, 
            String[] columns, 
            String selection, 
            String[] selectionArgs, //<<<<<<<<<<
            String groupBy, 
            String having, 
            String orderBy)

尝试使用:-

String selection = TaskEntry.COLUMN_CATEGORY_ID + " = ?";
String[] selectionArgs = new String[]{Integer.toString(mId)};
Cursor taskCursor = mDb.query(TaskEntry.TABLE_NAME, null, selection, 
    selectionArgs, null, null, null, null)

问题2

由于您定义的 category_id 列中没有TYPE,因此使用了默认的NUMERIC类型相似性,并且很遗憾,您遇到了TYPE AFFINITY至关重要的细微差别。

简而言之,您应使用以下适当的列类型(INTEGER是正确的,尽管TEXT也可以使用):-

    public static final String SQL_CREATE_TABLE = "CREATE TABLE " +
            TABLE_NAME + " (" +
            _ID + " INTEGER PRIMARY KEY, " +
            COLUMN_TASK_NAME + " TEXT UNIQUE NOT NULL, " +
            COLUMN_CATEGORY_ID + " INTEGER , " + //<<<<<<<<<<
            COLUMN_SKILL_ID + " INTEGER, " + //<<<<<<<<<<
            COLUMN_TASK_PD + ", " +
            COLUMN_TASK_DATE + ", " +
            COLUMN_TASK_PERIOD + ", " +
            COLUMN_TASK_FREQUENCY + ", " +
            COLUMN_TASK_ONBY + ", " +
            COLUMN_TASK_COMPLETION + ")";
  • 建议您为所有列都包含预期的类型。
  • 请注意,要使上述程序运行,您需要删除数据库或删除表。这可以通过执行以下一项操作来实现

    1. 卸载应用程序,然后重新运行,或者
    2. 清除应用程序的数据,然后重新运行,或者
    3. IF 已正确编码 onUpgrade 方法,然后可以增加数据库版本号(SQLiteOpenHelper超级调用的第4个参数)。
      • 经过适当编码的代码将要求它删除表然后创建表(通常将表删除,然后调用onCreate方法)
  • 如果您无法承受丢失数据的麻烦,则需要重命名表(使用ALTER TABLE),然后创建该表,然后从重命名的原始表中加载数据。

问题2-替代解决方案

更改列TYPE的另一种方法是使用 CAST 强制类型相似性,例如您可以使用:-

String selection = TaskEntry.COLUMN_CATEGORY_ID + " = CAST(? AS INTEGER)";

String selection = "CAST(" + TaskEntry.COLUMN_CATEGORY_ID  + " AS INTEGER)=?";
  • 使用以上两种方法均不需要重新创建表,但由于 messy ,因此不是首选方法。