2016-02-05 97 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(或更多)。

希望这会有所帮助。