-1

考虑一个保存在数据库中的两个表中的经典销售订单:

SALE_ORDER                   SALE_ORDER_ITEM
----------                   ---------------
id       integer             ...
...                           order_id        integer references sale_order (id)
                              item_id         integer references item (id)
                              quantity        integer
                              ...

出于这个问题的目的,请忽略 item_id 对另一个表的引用——这无关紧要。

我有一个包含订单的课程,例如:

public class SaleOrder {
    private int orderId;
    ...
    private List<BoughtItem> items;
    ....
}

订单可以更改(我的要求),更改可以包括列表中的项目:添加、删除的项目或更改的数量。当我在数据库中更新这个顺序时,最简单的事情就是delete from sale_order_item where order_id=<my_order_id>在列表中插入行。然而,这对我来说似乎效率很低,特别是考虑到该列表可以包含(可能)数百个不同的项目。(背景:这些是从超市到批发产品供应商的订单。)

另一种方法是查询数据库,然后将列表与游标进行比较,在必要时添加、删除或更新——这至少看起来同样低效。

  1. 还有另一种(第三种?)更有效的方法吗?
  2. 如果不是,这两者中哪一个更好?我总是使用第一个(全部删除,然后重新插入,但现在开始怀疑自己。

更新:数据库是 sqlite3(如果重要的话,在 android 上)

4

4 回答 4

0

如果您还没有,您需要在 sale_order_item 上进行 PK。

保留一个可以在更新数据库时重放的脏缓冲区。因此,如果用户更改了一个项目,请添加一个条目'update sale_order_item set item_id = "1234" where sale_order_item.id = "2222"'。

然后在与数据库通信时,回放这些更改。如何记录更改并不重要(记录 SQL 不是最有效的)。关键是能够识别每个项目的变化,或者项目的添加/删除,然后能够基于它创建 sql。

我希望它能给你一个想法。

于 2013-01-17T17:40:29.303 回答
0

这实际上取决于您是要更新项目还是只是重新插入它们。如果您不需要进行任何更新,如果您将现有项目添加到子句中,删除 + 插入就可以了(因此您不会删除新列表中的内容)

如果新列表总是黄金,那么使用游标没有意义,因为您已经有了数据,所以只需坚持删除/重新插入 - 它不像游标那样低效。

例如 t-sql

insert into sale_order_item(columns..)
select field1, 2, etc. from your_new_list a 
where not exists (select 1 from sale_order_item where item_id = a.item_id)
于 2013-01-17T17:42:36.003 回答
0

如果您没有原始项目 ID 列表,则必须至少删除所有不再在列表中的项目:

DELETE FROM sale_order_item
WHERE order_id = ?
  AND item_id NOT IN (id1, id2, ...)

如果您不知道记录是否已更改,则无法避免更新记录。

但是,可以避免插入已存在的记录:如果 (order_id, item_id) 列上有正确的主键,则可以使用INSERT OR REPLACEcommand

然而,这一切并不比简单DELETEINSERTs 更有效。

于 2013-01-17T18:50:38.833 回答
0
  1. 添加字段recordState:枚举{rfNone,rfInserted,rfUpdated,rdDeleted}。
  2. 将适当的代码添加到您的所有 setter 方法中,例如

    public void setData(String value) {
        if (!this.data.equals(value)) {
            this.data = value;
            if (getRecordState() == rfNone)
                setRecordState(rfUpdated);
        }    
    }
    

    如果记录类的任何值已更改,此代码将确保您将记录对象标记为已更新,当然如果此对象不是新构造的

  3. 从数据库读取的所有记录必须是初始的:recordState = rfNone

  4. 必须标记新添加的记录:recordState = rfInserted at creation
  5. 已删除的记录必须标记:recordState = rfDeleted(不要立即删除)
  6. 最后遍历记录对象列表并根据记录状态值进行适当的操作
于 2014-04-16T12:11:25.727 回答