2017-10-20 107 views
0

結論: Android的數據庫API 工作但文檔是嚴重不完整的。Sqlite:SqliteDatabase.delete()與原始查詢


我最近由於靈活性SQLite的提供了不強迫你創建表時指定數據類型運行到大腦失事情況。問題是我的思維模式假設每個數據類型都是一個通用字符序列(如果沒有指定),因此與數據庫交談的方式是通過java.lang.String

但是,你可別怪我要麼當你看到類似下面的方法:

int delete (String table, 
       String whereClause, 
       String[] whereArgs) 
SqlDatabase

Android docs

我有一個表,包括聯繫電話(我存儲爲java.lang.String)和時間戳作爲一項長期的領域。當我嘗試使用這種方法刪除一條記錄時,儘管進行了無數的調試,但它從未被刪除。

我檢查了一切,查詢是正常的,表是存在的,所有的檢查清單,直到偶然,我發現刪除時間戳,而以原始方式查詢時,而不是使用上述方法產生刪除成功,是這樣的:

DELETE FROM messages_records_table WHERE messageTimestamp = 1508494606000; 

,而不是執行以下操作:

DELETE FROM messages_records_table WHERE messageTimestamp = '1508494606000'; 

,或者

DELETE FROM messages_records_table WHERE messageTimestamp = "1508494606000"; 

電話號碼不是問題;這是插入/刪除中創建問題的時間戳

所以,我嘗試運行一個原始刪除查詢,刪除了引號(需要使用字符串/ varchar類型),並且它成功刪除。我用這個下面的方法:

db.execSQL(String sql, Object[] whereArgs) 

這裏要注意的關鍵一點是,相比於delete()Object[]String[]不同。我傳遞了一個Long對象來使它工作,但在delete()中傳遞Long.toString()似乎沒用。

所以我的問題是,我的分析是正確的,並delete() API基本上是無用的或有我錯過了picture..after都有些大,它是由精心Android團隊提供?

+0

您可以包括用於'delete'的實際代碼的 – MikeT

回答

1

SQLite支持multiple data types;儘管列類型沒有嚴格執行,但在某些情況下可能會自動轉換值(這稱爲affinity)。

當您的值存儲爲數字時,您應該將它們作爲數字訪問,而不是字符串。

Android數據庫API不允許在大多數函數中使用字符串以外的參數類型。這是一個可怕的設計錯誤。

要搜索一個號碼,或者使用execSQL(),它允許你使用數量的參數,或者轉換成字符串值回一個數字:

db.delete(..., "timestamp = CAST(? AS NUMBER)", 
      new String[]{ String.valueOf(ts) }); 
+0

好樣的!這解決了問題。這爲我探索更多SQlite警告提供了動力。不能相信我在這件事上浪費了一天的時間。謝謝。 –

0

的問題是我的心態,假設每個數據類型將是 一般的字符序列,如果沒有指定,因此,辦法 聊到數據庫是通過java.lang.String中。

我認爲這是真正的問題。

如果您未指定任何類型,例如

CREATE TABLE mytable (col1,col2,col3)

然後根據Determination of Column Affinity(3.1)規則3: -

3)若某列的聲明類型包含字符串「BLOB」,或者如果沒有指定 類型則該列具有親和性BLOB。

然後根據第3節

具有親和力BLOB列不喜歡一個存儲類超過 另一併且沒有試圖從一個存儲的類 數據強迫到另一個。

我個人從來沒有與刪除的問題。然而,我必須根據ROWID總是刪除的傾向。

這裏的工作示例使用情況表明,delete也不是一無是處,並根據長期刪除。然而,列所有類型的INTEGER的: -

 int pudeletes; 
     int sldeletes; 
     int rdeletes; 
     int pdeletes; 

     if(doesProductExist(productid)) { 

      // if not in a transaction then begin a transaction 
      if(!intransaction) { 
       db.beginTransaction(); 
      } 

      String whereargs[] = { Long.toString(productid)}; 

      // Delete ProductUsage rows that use this product 
      pudeletes = db.delete(
        DBProductusageTableConstants.PRODUCTUSAGE_TABLE, 
        DBProductusageTableConstants.PRODUCTUSAGE_PRODUCTREF_COL + 
          " = ?", 
        whereargs 
      ); 

      // Delete ShopList rows that use this product 
      sldeletes = db.delete(
        DBShopListTableConstants.SHOPLIST_TABLE, 
        DBShopListTableConstants.SHOPLIST_PRODUCTREF_COL + 
          " = ?", 
        whereargs 
      ); 

      // Delete Rules rows that use this product 
      rdeletes = db.delete(
        DBRulesTableConstants.RULES_TABLE, 
        DBRulesTableConstants.RULES_PRODUCTREF_COL + 
          " = ?", 
        whereargs 
      ); 

      // Delete the Product 
      pdeletes = db.delete(
        DBProductsTableConstants.PRODUCTS_TABLE, 
        DBProductsTableConstants.PRODUCTS_ID_COL + 
          " = ?", 
        whereargs 
      ); 

      // if originally not in a transaction then as one was started 
      // complete and end the transaction 
      if(!intransaction) { 
       db.setTransactionSuccessful(); 
       db.endTransaction(); 
      } 
     }