2016-02-05 89 views
0

我正在使用MySQL 5.6,我有這個問題。 我正在嘗試改進此案件的批量更新策略。MySQL:批量更新表

我有一張表,名爲reserved_ids,由外部公司提供,用於爲其發票分配唯一的ID。沒有其他辦法可以做到這一點;我無法使用auto_increment字段或模擬序列。

我有這樣的PL僞代碼,使這項任務:

START TRANSACTION; 

OPEN invoice_cursor; 

read_loop: LOOP 
    FETCH invoice_cursor INTO internalID; 
    IF done THEN 
     LEAVE read_loop; 
    END IF; 


    SELECT MIN(SECUENCIAL) 
    INTO v_secuencial 
    FROM RESERVED_IDS 
    WHERE COUNTRY_CODE = p_country_id AND INVOICE_TYPE = p_invoice_type; 

    DELETE FROM RESERVED_IDS WHERE SECUENCIAL = v_secuencial; 

    UPDATE MY_INVOICE SET RESERVED_ID = v_secuencial WHERE INVOICE_ID = internalID; 


END LOOP read_loop; 

CLOSE invoice_cursor; 

COMMIT; 

所以,這是一個需要 - 刪除 - 分配,然後採取下一個 - 刪除 - 分配...等等。

這可行,但速度非常慢。 我不知道是否有任何方法以更快的速度完成這項任務。 我正在尋找類似於的內容INSERT INTO SELECT ...,但帶有UPDATE語句,可以直接分配1000或2000個ID,並且不會一個接一個。

請任何建議對我很有幫助。 非常感謝。

編輯1:我已經加入WHERE子句細節,因爲它是由用戶@vmachan要求。在UPDATE ... INVOICE子句中,我沒有按照其他標準過濾,因爲我有直接和索引的發票ID,我想更新它。謝謝

+0

你可以發佈'WHERE'條件從'RESERVED_IDS'選擇並更新'MY_INVOICE'表..? – vmachan

+0

@vmachan,謝謝你的回答。我已經按照你的要求添加了SQL細節。我希望編輯的問題比以前更清楚。再次感謝。 –

回答

0

最後,我有這個解決方案。這比我最初的方法快得多。

更新查詢是

set @a=0; 
set @b=0; 


UPDATE MY_INVOICE 
INNER JOIN 
(
    select 
     F.invoice_id, 
     I.secuencial as RESERVED_ID, 
     CONCAT_WS(/* format your final invoice ID */) AS FINAL_MY_INVOICE_NUMBER 
    FROM 
    (
    select if(@a, @a:[email protected]+1, @a:=1) as current_row, internal_id 
    from MY_INVOICE 
    where reserved_id is null 
    order by internal_id asc 
    limit 2000 
    ) F 
    INNER JOIN 
    (
    SELECT if(@b, @b:[email protected]+1, @b:=1) as current_row, secuencial 
    from reserved_ids 
    order by secuencial asc 
    limit 2000 
    ) I USING (CURRENT_ROW) 
) TEMP MY_INVOICE.internal_id=TEMP.INTERNAL_ID 
SET MY_INVOICE.RESERVED_ID = TEMP.RESERVED_ID, MY_INVOICE.FINAL_MY_INVOICE_NUMBER=TEMP.FINAL_MY_INVOICE_NUMBER 

所以,用自動生成和相關secuencial號@a和@b,我們可以加入兩個不同的和喜歡MY_INVOICE和RESERVED_IDs沒有相關的表。

如果你要檢查這個解決方案,請按照下列步驟執行此棘手更新:

  • 執行@a然後第一內選擇在一個孤立的方法:select if(@a, @a:[email protected]+1, ...
  • 執行@b然後在一個孤立的方式,第二內選擇:select if(@b, @b:[email protected]+1, ...
  • 執行@a,@b和大選擇構建TEMP附配表:select F.invoice_id, ...
  • 執行UPDATE
  • 最後,從RESERVED_ID表中刪除分配的ID。

指定時間急劇減少。我最初的解決方案是一個接一個;有了這個,你可以在一個單獨的(確定的,有點棘手的)更新中指定2000(或更多)。

希望這會有所幫助。