3

SQLiteデータベースを使用しています。1つまたは2つの行の値が更新されるたびに、テーブルに継続的に更新が行われます。

次に例を示します。TABLE1には20行あり、一部の行の値が更新されます。

TABLE1でどの行が更新されたかを知ることができますか?

私には解決策がありますが、パフォーマンスは私にとって重要です。カーソルは、すべての行を選択するselectクエリでデータオブザーバーを登録します。更新がある場合は、更新された値で20行全体を取得し、コーディングを行います。したがって、100行ある場合は、すべてをループする必要があります。これは、ローエンドデバイスにとって面倒な作業です。

カーソルを使用してAndroidのテーブルで更新された行を取得する方法という解決策をご協力ください。

4

3 に答える 3

9

テーブルを変更できる場合は、タイプTIMESTAMPの新しい列'modified_time'を追加します。行が更新されるたびにこの列を更新します。

ここで、どの行が更新されたかを知りたい場合は、次のSQLクエリを実行します。

select _id from table2 where modified_time = (select max(modified_time) from table2)

このクエリの結果は、最新に更新されたすべての行のIDを示します。

編集: コメントで述べたように、「...サーバーは変更された値でデータをテーブルにプッシュします。更新値を取得して他のテーブルに更新する必要があります」、あなたにとって最良のオプションは、DBにトリガーを作成することです。最初のテーブルの更新に基づいて2番目のテーブルを更新します。これがアプローチです。

サーバーがデータを「table1」にプッシュし、更新された行を監視するとします。自動的に更新される別のテーブル2を作成します(または既存のものを使用します)。

次に、次のようにトリガーを作成します。

CREATE TRIGGER trigger1 AFTER UPDATE ON table1
 BEGIN
  update table2 SET modified_time = datetime('now') WHERE row_id = old._id;
 END;

もちろん、table2は異なりますが、トリガーを使用してtable2の行を自動的に挿入または更新できるという考え方です。詳細については、次のSO投稿を参照してください。

sqlite3は「updated_on」日時フィールドを自動的に更新するトリガーをサポートしていますか?

SQLiteトリガーを使用して「LastModified」フィールドを更新する

サンプルアプリケーション: 説明したシナリオに基づいて、Androidアプリケーションでのトリガーの使用を示すサンプルアプリケーションを作成しました。Eclipseプロジェクトはここからダウンロードできます--trigger_example_eclipse_project.zip

簡単に言うと、サンプルアプリケーションには、製品価格の更新を受け取る製品テーブルがあります。そのため、トリガーを介して製品テーブルの更新に基づいて自動的に更新される別の更新テーブルを作成します。

EditTextフィールドとボタンによって製品テーブルの更新をシミュレートするUIがあります。また、最近の更新を表示するために、カーソルを使用して更新テーブルからデータをフェッチするListViewがあります。

ここにDbHelper.javaからのいくつかの関連するコードスニペットがあります

public class DbHelper extends SQLiteOpenHelper {

    public static final String TABLE1 = "product";
    public static final String TABLE2 = "updates";

    public static final String COL_ID = "_id";
    public static final String COL_NAME = "name";
    public static final String COL_PRICE = "price";
    public static final String COL_MODIFIED_TIME = "modified_time";

    public static final String KINDLE = "Kindle";

    private static final String SQL_CREATE_TABLE1 = 
            "CREATE TABLE product (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, price INTEGER);";

    private static final String SQL_CREATE_TABLE2 = 
            "CREATE TABLE updates (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, price INTEGER, modified_time TIMESTAMP);";

    private static final String SQL_CREATE_TRIGGER = 
            "CREATE TRIGGER price_update AFTER UPDATE OF price ON product"+
            "   BEGIN" +
            "       INSERT INTO updates(name,price,modified_time) VALUES(old.name,new.price,datetime('NOW'));"+
            "   END;";

    public DbHelper(Context context) {
        super(context, "sampledb", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_TABLE1);
        db.execSQL(SQL_CREATE_TABLE2);
        db.execSQL(SQL_CREATE_TRIGGER);

        ContentValues cv = new ContentValues();
        cv.put(COL_NAME, KINDLE);
        cv.put(COL_PRICE, 99);
        db.insert(TABLE1, null, cv);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
    }

}
于 2013-02-28T17:39:10.817 に答える
3

更新時に現在の時刻で更新されるLAST_UPDATE_TIMEのような列を保持できます。

次に、LAST_UPDATE_TIME>が必要な時間を含むすべての行をクエリできます。

テーブルを変更できない場合、同じ列で新しいテーブルを作成できますか?次に、両方のテーブルを更新し、必要に応じて新しいテーブルから値をフェッチし、使い終わったら新しいテーブルからのみ値を削除します。

于 2013-03-06T13:15:40.103 に答える
1

ContentProviderを正しく実装すると、挿入または更新によって行のIDが返される可能性があります。

少し複雑ですが、GoogleのIOScheduleアプリプロバイダーコントラクトクラスを確認し、コントラクトのRoomクラスと、insertまたはupdateメソッドのプロバイダーの「Room」ケースを確認してください。
Uriが返されることがわかります。この設計アプローチでは、最後の要素(最後のスラッシュの後)が挿入/更新された行のIDです。

私はこのアプローチがあなたを助けるかもしれません、そしてあなたがあなたの仕事を成し遂げるためにあなたがグーグルのソースコードを理解することができるということ(私は理解するのが少し難しいと思いました)

于 2013-03-10T22:55:32.410 に答える