2017-10-20 7 views
0

結論: AndroidのデータベースAPI の作業がドキュメントはひどく不完全です。Sqlite:SqliteDatabase.delete()対未処理クエリ


私は最近、原因sqliteは、テーブルを作成するときに、データ型を指定するように強制しないことによって提供して柔軟性に脳の解体状況に遭遇してきました。問題は私の考え方であり、指定されていなければすべてのデータ型が一般的な文字列であると仮定し、したがってデータベースとの対話方法はjava.lang.Stringです。

しかし、あなたは以下のようなメソッドを見たとき、あなたはどちらか私を責めることはできない。

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

SqlDatabaseクラスでAndroid docsから。

Iは電話番号(Iは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型で必要な)生の削除クエリを実行しようとしましたが、削除に成功しました。ここで注目すべき重要なことは、Object[]delete()に比べString[]と異なっていることである

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

:私は、このために、以下の方法を使用していました。私はそれを動作させるためにオブジェクトにロングを渡したが、Long.toString()delete()に渡すことは役に立たないようだ。

私の分析は正しいですか?delete() APIは基本的に役に立たないですか、もっと大きな画像を見逃してしまったのですか?それ以来、Androidチームは慎重に提供していますか?

+0

あなたは 'DELETE'のために使用される実際のコードを含めることができます's – 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(); 
      } 
     } 
関連する問題