FTS中virtual table更新數據失敗

一、問題描述

項目中使用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));

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章