3

我正在使用 SQLite 数据库。每次更新 1 或 2 行值时,表中会持续更新。

例如:现在 TABLE1 中有 20 行,其中一些行值得到更新。

我们能知道 TABLE1 中哪些行得到了更新吗?

我有解决方案,但性能对我很重要。游标使用选择所有行的选择查询注册数据观察者,当有更新时,我检索具有更新值的整个 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。

编辑: 正如您在评论中提到的“...服务器将数据推送到具有更改值的表中。我需要获取更新值并更新到其他表”,您最好的选择是在数据库中创建一个触发器将根据第一个表的更新更新第二个表。这是方法。

假设服务器将数据推送到“table1”并且您想要监控更新的行。创建另一个 table2(或使用现有的),它将自动更新。

现在,创建一个触发器,如下所示:

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 应用程序中使用 Trigger。您可以在此处下载 Eclipse 项目 - trigger_example_eclipse_project.zip

简而言之,示例应用程序有一个产品表,它接收产品价格的更新。因此,我们创建了另一个更新表,它将通过触发器根据产品表上的更新自动更新。

有一个 UI 可以通过 EditText 字段和按钮来模拟产品表的更新。为了显示最近的更新,我们有一个 ListView,它使用 Cursor 从更新表中获取数据。

这里有一些来自 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 应用程序,查看ProviderContract类,查看 Contracts 中的Room类以及插入或更新方法中 Provider 中的“Room”案例。
您会看到将返回一个 Uri,在这种设计方法中,最后一个元素(在最后一个斜杠之后)是插入/更新行的id

我这种方法可以帮助你,并且你可以理解谷歌的源代码来完成你的工作(我发现它有点难以理解)

于 2013-03-10T22:55:32.410 回答