已验证的现有列上的 SQLite 数据库“没有此类列”错误
Posted
技术标签:
【中文标题】已验证的现有列上的 SQLite 数据库“没有此类列”错误【英文标题】:SQLite database "No such column" error on verified existing column 【发布时间】:2021-12-01 10:20:21 【问题描述】:我遇到了“SQLiteException:没有这样的列:”错误。我正在尝试编写一些代码来检查数据库中是否存在一个项目,然后再存储它,我不知道这是否是最好的方法,但它可以完成这项工作。或者不是真的,当我将所有数字用于我正在搜索的特定列中的数据时,它工作正常。但是,如果列数据中有任何字母,它就会崩溃。
主活动
private ConversationsDatabaseHelper db;
//onCreate stuff here
db = new ConversationsDatabaseHelper(this);
String threadId = "886";
Log.d(TAG, "dbTest: EXISTS; " + db.conversationExists(threadId));
databaseHelper 类中是 converstionExists 函数
public boolean conversationExists(String threadId)
// Select All Query
String selectQuery = "SELECT * FROM " + Conversations.TABLE_NAME + " WHERE " +
Conversations.COLUMN_THREAD_ID + " LIKE " + threadId;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
boolean returnValue = false;
// Check if this message exists
if (cursor.moveToFirst())
returnValue = true;
// close db connection
db.close();
return returnValue;
因此,如果我使用例如“886”作为 threadId 值,那么一切都很好。如果我创建一个匹配 threadId 的行,那么它返回 true。在这种情况下,我没有那么错。 堆栈跟踪...
dbTest:存在;假的
但使用 a886 会导致
原因:android.database.sqlite.SQLiteException:没有这样的列:a886(代码 1 SQLITE_ERROR):,编译时:SELECT * FROM conversations WHERE thread_id LIKE a886
而 88a6 导致了这个
Caused by: android.database.sqlite.SQLiteException: unrecognized token: "88a6" (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM conversations WHERE thread_id LIKE 88a6
看起来混合字母和数字可能是这里的部分原因,但不应该是因为该列是为保存 TEXT 数据类型而创建的。这是数据库创建表查询字符串。
public static final String TABLE_NAME = "conversations";
public static final String COLUMN_ID = "id";
public static final String COLUMN__ID = "_id";
public static final String COLUMN_GROUP_ID = "group_id";
public static final String COLUMN_LAST_MESSAGE_ID = "last_message_id";
public static final String COLUMN_THREAD_ID = "thread_id";
public static final String COLUMN_ADDRESS = "address";
public static final String COLUMN_CONTACT = "contact";
public static final String COLUMN_BODY = "body";
public static final String COLUMN_DATE = "date";
public static final String COLUMN_TYPE = "type";
public static final String COLUMN_STATE = "state";
public static final String COLUMN_READ = "read";
public static final String COLUMN_STATUS = "status";
public static final String COLUMN_CT = "ct";
// Create table SQL query
public static final String CREATE_TABLE =
"CREATE TABLE " + TABLE_NAME + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY ,"
+ COLUMN_LAST_MESSAGE_ID + " TEXT,"
+ COLUMN__ID + " TEXT,"
+ COLUMN_GROUP_ID + " TEXT,"
+ COLUMN_THREAD_ID + " TEXT,"
+ COLUMN_ADDRESS + " TEXT,"
+ COLUMN_CONTACT + " TEXT,"
+ COLUMN_BODY + " TEXT,"
+ COLUMN_DATE + " TEXT,"
+ COLUMN_TYPE + " TEXT,"
+ COLUMN_STATE + " TEXT,"
+ COLUMN_READ + " TEXT,"
+ COLUMN_STATUS + " TEXT,"
+ COLUMN_CT + " TEXT"
+ ")";
我对此感到“大吃一惊”,我们将不胜感激。
【问题讨论】:
我建议您了解 Room API。这使得使用 SQLite 数据库比编写原始 html 更容易。 看看this article关于查询表是否存在。 【参考方案1】:值 a886 应该是文本/字符串文字而不是数字文字。因此,它应该用单引号括起来。错误是因为:-
a886 失败,未找到任何列,因为它被视为列名,因为它不是文字。
虽然 88a6 首先不是有效的文字(由于 a),因此是列名,但随后是无效的列(不能以数字开头,除非包含在内)名称,因此不是已知的标记。
见Literal Values (Constants)
您可以使用(将 threadId 括在单引号中)来解决此问题:-
String selectQuery = "SELECT * FROM " + Conversations.TABLE_NAME + " WHERE " +
Conversations.COLUMN_THREAD_ID + " LIKE '" + threadId + "'";
但是,建议使用绑定参数来防止 SQL 注入。
因此建议使用:-
String selectQuery = "SELECT * FROM " + Conversations.TABLE_NAME + " WHERE " +
Conversations.COLUMN_THREAD_ID + " LIKE ?";
还有:-
Cursor cursor = db.rawQuery(selectQuery, new String[]threadId);
即这 ?替换为正确包含的 threadId 值。
您可能希望考虑使用方便的query 方法而不是 rawQuery,这将是:-
Cursor cursor = db.query(Conversations.TABLE_NAME,null,Conversations.COLUMN_THREAD_ID + " LIKE ?", new String[]theadId,null,null, null);
SQL 专为您构建。
看起来混合字母和数字可能是这里的部分原因,但不应该是因为该列是为保存 TEXT 数据类型而创建的。
SQlite 以任何类型存储任何值都没有问题。类型本身几乎可以是任何东西(规则用于确定结果类型),它只是将要存储的值的指示。唯一的例外是 rowid 或 rowid 的别名必须是整数值(您的 id 列是 rowid 列的别名)。
【讨论】:
注释强调:使用绑定参数,而不是字符串连接,以避免SQL注入攻击。 感谢这解决了问题。此外,我不相信我会受到任何可能的注入攻击,因为没有一个变量是用户可访问的。线程 id 是从 SMS thead_id 列中获取的,据我所知,用户无法编辑该列。同时,你永远不能太安全。再次感谢,这真的帮助了我。以上是关于已验证的现有列上的 SQLite 数据库“没有此类列”错误的主要内容,如果未能解决你的问题,请参考以下文章