一、问题描述
项目中使用FTS实现本地数据检索功能,创建以下表:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS fts_index USING fts4(" +
content +","+
cid + " integer PRIMARY key,tokenize=mmicu);" ) ;
}
与表对应建立的数据结构
public class Index implements Serializable {
/**
* 索引id
* 如果在虚拟表中使用integer 做为主键会导致的问题
* https://www.sqlite.org/lang_createtable.html#rowid
*/
public long cid;
/**
* 搜索内容
*/
public String content;
}
当对表中已经存在的数据,进行更新的时候,数据不能成功更新到表中。更新方法如下:
ContentValues values = new ContentValues();
values.put("content", "要更新的数据值");
String whereClause = "cid = ?";
DBManager.getInstance().update("tfs_index", values, whereClause, new String[]{"要更新记录的cid的值"});
使用以上方法数据更新失败。
二、数据更新失败的原因
1、long 类型的数据转为integer的时候,数据的精度会丢失,此处会导致异常。在早期的版本中此处是一个bug.
2、rowid主键问题。
看一下链接中 ROWIDs and the INTEGER PRIMARY KEY 的部分内容
https://www.sqlite.org/lang_createtable.html#rowid
三、解决方法。
对以上红色标记的部分修改如下:
@Override public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS fts_index USING fts4(" + content +","+ cid + " varchar(200) PRIMARY key,tokenize=mmicu);" ) ;
}
public class Index implements Serializable {
/**
* 索引id * 如果在虚拟表中使用integer 做为主键会导致的问题
* https://www.sqlite.org/lang_createtable.html#rowid
*/
public long cid;
/** * 搜索内容 */
public String content;
}
修改后就可以正常更新数据。
在创建虚拟表时,建议检索的参数类型和表中保持一直,根据主键查询和更新数据才不会出现问题。
提醒:
使用interger primary key的时候,他会导致一些异常,并且不建议如此做。
The exception mentioned above is that if the declaration of a column with declared type "INTEGER" includes an "PRIMARY KEY DESC" clause, it does not become an alias for the rowid and is not classified as an integer primary key. This quirk is not by design. It is due to a bug in early versions of SQLite. But fixing the bug could result in backwards incompatibilities. Hence, the original behavior has been retained (and documented) because odd behavior in a corner case is far better than a compatibility break. This means that the following three table declarations all cause the column "x" to be an alias for the rowid (an integer primary key):
- CREATE TABLE t(x INTEGER PRIMARY KEY ASC, y, z);
- CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x ASC));
- CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x DESC));

本文详细介绍了在使用SQLite的全文搜索(FTS)功能时,遇到virtual table数据更新失败的问题。问题源于long数据转换为integer时精度丢失以及rowid主键的不当使用。解决方法是正确设置virtual table的创建语句,避免将integer作为主键,确保数据类型匹配,从而修复数据更新异常。

2042

被折叠的 条评论
为什么被折叠?



