SQLiteDatabase.insertに注意してください

Androidのデータベースをいじくり回すと、非常に不愉快なことに出くわしました。データを挿入するためのSQLiteDatabaseメソッドは、ドキュメントに書かれているとおりに機能しません。 タスクは簡単でした。レコードを挿入し、別のテーブルで使用するためのキーを取得します。 必要なレコードが既に利用可能な場合、この古いレコードのキーを知りたいです。 この最も古いキー以外のものを入手できることが判明しました。



これを理解するために、猫にいくつかの実験をしなければなりませんでしたが、今では何かがより明確になりました。



まず、AndroidがSQLiteDatabaseで私たちに約束することを見てみましょう。



insert()が最も簡単な方法です。 挿入されたキーを返すか、何か問題が発生した場合は-1を返します。



insertOrThrow() -説明は前の説明と完全に一致しますが、メソッドがSQLExceptionをスローすることが追加されます。 名前から判断すると、-1を返す代わりにSQLExceptionがスローされることが予想されますが、これまでのところ確実性はありません。



insertWithOnConflict() -これは最も興味深いものです。 IGNOREアルゴリズムOR -1が競合に使用された場合、メソッドは新しいレコードのキーまたは既存のレコードのキーを返すと約束されています。 SQLExceptionについては何も言われていないことも忘れないでください。



それでは実際に何が起こるか見てみましょう。 簡単なテーブルを作成して、異なる競合解決アルゴリズムを設定してみましょう(なしを含む)。 ロールバックとアボートをチェックしませんでした。この場合の動作は、明らかに失敗に似ているため、無視することに最も興味がありました。



いくつかの一意の値をテーブルに挿入し、競合する値を追加してください。 これらすべてのメソッドが競合をどのように処理するかを見てみましょう。



競合解決アルゴリズムが指定されていない場合、単純なinsert()は-1(約束どおり)を返し、insertOrThrow()とinsertWithOnConflict()は両方ともSQLiteConstraintExceptionをスローします。 そして、これがinsertOrThrow()に対して正しい場合、insertWithOnConflict()から-1が期待されます。 同じことが「失敗」アルゴリズムでも起こります。



'replace'アルゴリズムは、すべてのメソッドを正常に機能させました。古いレコードを削除し、新しいレコードを挿入して、そのキーを返しました。



しかし、そのような必要な「無視」により、それは完全に残念なことが判明しました。 エラーをスローしたメソッドはありません(-1またはSQLiteConstraintException)。 すべてが一緒に特定の番号を返しました-おそらく、テーブルに挿入された最後のレコードのキーです。 もちろん、これは私たちが約束したものではありません。



一般的に、ドキュメントは信頼できません。 どのメソッドでも、最も予期しない値を返すか、例外をスローできます。 しかし、目的の結果を達成することはできませんでした。単一のメソッドが既存のレコードのキーを競合で返すことはできませんでした。



All Articles