java - db.query 无法使用整数字段进行选择
问题描述
我有一个带有 2 个表的数据库 - 类别和任务,每个任务都有一个与类别 _id 字段相关联的字段。问题是 tasks.category_id = current category id 上的选择返回空光标。
在调试模式下可以看出选择标准是正确的;数据库字段被检查并具有正确的值;删除选择标准会正确返回完整的数据库。如果在第一个参数中进行了所有选择,则将 .query 替换为 .rawQuery 会返回正确的值。这个效果很好:
String selection = "select * from task where category_id = " + mId;
Cursor taskCursor = mDb.rawQuery(selection, null);
主要活动:
//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)
任务光标为空。
数据库合同类:
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 + ")";
}
解决方案
你似乎有几个问题。
第一期
选择参数,查询的第四个参数,应该是 aString[]
而不是 a String
。
IE
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 期
由于您定义了没有 TYPE 的category_id列,因此使用了 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 + ")";
- 建议您包含所有列的预期类型。
请注意,要运行上述内容,您需要删除数据库或删除表。这可以通过执行以下操作之一来实现
- 卸载应用程序然后重新运行,或
- 清除应用程序的数据然后重新运行,或
- 如果对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)=?";
- 使用上述任何一种方法都不需要重新创建表,但不是更可取的方法,因为它很混乱。
推荐阅读
- python - 部分付款后如何将发票标记为已付款
- javascript - 在不调用 click 命令的情况下使用 Cypress 单击按钮?
- c++ - 用其他变量打印 c++ 变量会改变值
- reactjs - React Redux,来自 reducer 的值在 console.log 上显示为 undefined
- python - 使用正则表达式提取找到第二个匹配项
- python - 使用来自具有特定列值的另一个数据框的行创建一个新的数据框
- c# - 如何使用 MessageWebSocket 发送 ping 以保持与服务器的连接
- json - 动态键值的json解析中的颤振问题
- javascript - Javascript仅操作多个组件中的一个
- google-apps-script - 未找到脚本函数:doGet (AGAIN !!! )