2013-01-17 161 views
-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上,如果該事項)

+0

是否使用的是RDBMS基於recordState值適當的行動? – Quassnoi

+0

@Quassnoi oops,忘記包含該信息。它是android上的sqlite。 –

+0

我很想知道downvote的用途。 –

回答

0

您需要sale_order_item一個PK如果你還沒有它,

保留一個髒緩衝區,你可以在更新數據庫時重放所以如果用戶改變一個項目,添加一個條目'update sale_order_item set item_id =「1234」where sale_order_item.id =「2222」'。

然後,當涉及到與數據庫通信時,請回放這些更改。記錄更改的方式並不重要(記錄SQL不是最有效的)。關鍵是能夠識別每個項目中發生了什麼變化,或者添加/刪除項目,然後能夠基於此創建sql。

我希望它給你一個想法。

+0

這個問題的一大問題是它打破了功能的分離。現在我有我的'SQLiteOpenHelper'子類,它具有'updateOrder(SaleOrder order)'方法。根據你的答案,我將不得不在'SaleOrder'類中創建SQL語句,這並不是特別好。當然,我可以用另一種方式跟蹤這些變化,但它有多高效?尤其是記憶效率與速度。請記住,該應用程序將在移動設備上運行,因此應儘量減少內存佔用。 –

+0

SaleOrder爲什麼不能保持1)是否髒,2)如果髒了,是否做了特定的更改?現在支付或稍後支付... –

+0

最終,我開發了這個想法並且解決了功能分離問題。 「訂單」跟蹤「添加」,「刪除」和「更新」項目;他們的數據庫訪問類獲取這些項目的列表並從那裏更新。 –

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) 
+0

我在android上使用sqlite,所以語法不同。新的列表是黃金的,所以刪除/重新插入將在最後提供正確的數據。 –

0

如果你沒有項目ID的原始列表,你必須至少刪除所有不再不在你的列表中的那些項目:

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

你無法避免更新記錄如果你不知道他們是否已經改變。

但是,可以避免插入已存在的記錄: 如果在(order_id,item_id)列上有適當的主鍵,則可以使用INSERT OR REPLACE command

但是,所有這些都不是更有效率,只是簡單的DELETEINSERT s。

0
  1. 添加字段recordState:enum {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. 所有記錄從數據庫中讀取必須initialy:recordState = rfNone

  4. 新添加的記錄必須註明:recordState = rfInserted在創建
  5. 刪除的記錄必須註明:recordState = rfDeleted(不要立即刪除)
  6. 在記錄對象的結束導線列表和使
相關問題