Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sqlite 更新/插入/删除数据库中的子记录_Sqlite_One To Many_Updates - Fatal编程技术网

Sqlite 更新/插入/删除数据库中的子记录

Sqlite 更新/插入/删除数据库中的子记录,sqlite,one-to-many,updates,Sqlite,One To Many,Updates,考虑保存在数据库中的两个表中的经典销售订单: SALE_ORDER SALE_ORDER_ITEM ---------- --------------- id integer ... ... order_id integer references sale_order (id)

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

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;
    ....
}
公共类销售订单{
私有int-orderId;
...
私人清单项目;
....
}
订单可以更改(我的需求),更改可以包括列表中的项目:添加的项目、删除的项目或数量更改的项目。当我在数据库中更新这个订单时,最简单的方法显然是
从销售订单中删除订单id=
中的项目,然后插入列表中的行。然而,这对我来说似乎效率很低,特别是考虑到列表可能包含(可能)数百个不同的项目。(背景:这些是从超市到批发产品供应商的订单。)

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

  • 是否有其他(第三种?)更有效的方法
  • 如果不是,两个中哪一个更好?我总是使用第一个(全部删除,然后重新插入),但现在开始怀疑自己

  • 更新:数据库是sqlite3(在android上,如果这很重要)

    如果您还没有PK-on-sale\u-order\u商品,您需要它

    保留一个脏缓冲区,以便在更新数据库时重播。因此,如果用户更改了项目,请添加一个条目“更新销售订单项目集项目”\u id=“1234”where sale\u order\u item.id=“2222”

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


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

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

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

    e、 g.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)
    

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

    DELETE FROM sale_order_item
    WHERE order_id = ?
      AND item_id NOT IN (id1, id2, ...)
    
    如果不知道记录是否已更改,则无法避免更新记录

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

    然而,所有这些都没有比简单的
    DELETE
    INSERT
    s更有效

  • 添加字段记录状态:枚举{rfNone,rfInserted,rfUpdated,rdDeleted}
  • 向所有setter方法添加适当的代码,如

    public void setData(String value) {
        if (!this.data.equals(value)) {
            this.data = value;
            if (getRecordState() == rfNone)
                setRecordState(rfUpdated);
        }    
    }
    
    如果记录类的任何值发生了更改(当然,如果该对象不是新构造的),此代码将确保您将记录对象标记为已更新

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

  • 新添加的记录必须在创建时标记为:recordState=rfInserted
  • 必须标记已删除的记录:recordState=rfDeleted(不要立即删除)
  • 最后,遍历记录对象列表,并根据记录状态值执行适当的操作

  • 你用的是哪种RDBMS?@Quassnoi oops,忘了包含这些信息。它是android上的sqlite。我想知道否决票是为了什么。一个大问题是它打破了功能的分离。现在我有了我的
    SQLiteOpenHelper
    子类,它有方法
    updateOrder(SaleOrder)
    。根据您的回答,我必须在
    SaleOrder
    类中创建SQL语句,这不是特别好。当然,我可以用另一种方式跟踪更改,但效率如何?特别是内存效率与速度的关系。记住,应用程序要在移动设备上运行,所以应该尽量减少内存占用。为什么SaleOrder不保留1)是否脏,2)如果脏,具体更改是什么?现在付款或以后付款…最终,我发展了这个想法,并围绕功能分离展开了工作<代码>订单跟踪“添加”、“删除”和“更新”项目;数据库访问类从中获取这些项目的列表和更新。我在android上使用sqlite,所以语法不同。新列表是金色的,因此删除/重新插入将在最后给出正确的数据。