2013-04-29 57 views
3

需要帮助,我需要从表B. 只有2列更新表A(表A,B在普通只有2列 - 的col1a,co11b :: col2a,col2b在更新1个千万行

示例脚本:我想与col1b其中col2a = col2b

UPDATE a 
    SET col1a = (SELECT col1b 
        FROM b 
       WHERE a.col2a = b.col2b) 

由于数据是巨大的,我想每隔一段时间(比如5000条记录) 可否请您建议提交行更新所有的col1a值。

+0

您可以使用LIMIT关键字,甚至做用,如果你拿到“身份证”字段中输入您自己的时间间隔一(1 RelevantUsername 2013-04-29 21:27:08

+7

这几天1000万行数据并不多。你为什么要间隔提交?这至少会让事情变得更慢。这将需要更多的代码。它会产生更多的“UNDO”和“REDO”。你确定这就是你想要做的? – 2013-04-29 21:32:01

+0

我必须定期提交。但不确定在要提交的行号上。 它是过程的输入参数。 我必须根据输入参数提交。 – 2013-04-29 21:44:35

回答

0

如果你想和如果可能在你的环境中,你可以

create table newtable as select .... from oldtable 

这将创建一个新表。

然后重新创建索引,重命名这两个表并重新创建约束。

+0

这是有道理的,但仍然在创建和删除之后:D +1 – 2013-04-30 03:00:11

4

由于您在问题中显示的查询包含子查询,因此会对正在更新的每一行在表b上执行查找。这可能会很慢,无论如何,更新是一个足够慢的操作。

根据您的表格设计,我会尝试“更新视图”或合并。 UPDATE的能力取决于存在“保留键的连接”。如果你没有这个,UPDATE将不起作用。如果没有某种表格的DDL,就很难给出正确的答案。

UPDATE (
    select col1a, col1b, col2a, col2b 
    from 
    a join b on (a.col2a = b.col2b) 
) 
set col1a = col1b; 

如果更新不起作用,您可以尝试MERGE。这应该在比更新更多的情况下工作。

merge into a 
using b on (a.col2a = b.col2b) 
when matched then update set a.col1a = b.col1b 

这两种语句的优点是它们能够处理整个数据集而不是一次更新一行。要使更新得以良好执行可能很困难。

如果有任何索引,可能还需要删除col1a列中的任何索引。

+0

我只提到'MERGE'语句的唯一警告是它需要'WHEN NOT MATCHED'子句和'INSERT'语句,所以它在这种情况下可能不是最好的选择。然而,我确实认为删除'col1a'上的索引将是很好的,因为可以消除任何限制,因为这可以加速更新。 – 2013-04-30 03:06:53

+0

@MauriceReeves我认为'INSERT'子句也是必需的,但是当我查看10r2文档时SQL似乎是可选的,而SQL小提琴在我离开时没有抱怨。 – 2013-04-30 03:26:48

+0

奇怪。当我在Oracle 11g上建立'MERGE'语句时,当我没有包含'INSERT'时,我收到了关于丢失子句的抱怨等。想知道10r2是否更加宽容...... – 2013-04-30 04:03:57

1

谢谢大家。我得到了解决方案。 我一直在寻找的解决方案类似下面

 CREATE OR REPLACE PROCEDURE xxwv_cc_token_conversion (
    p_source_table IN VARCHAR2, 
    p_dest_table  IN VARCHAR2, 
    p_column_name IN VARCHAR2, 
    p_commit_row  IN NUMBER 
) 
IS 
    TYPE cv_typ IS REF CURSOR; 

    t_cur cv_typ; 

    TYPE token_num IS TABLE OF xxwv_ap_token_test2.token_number%TYPE 
     INDEX BY BINARY_INTEGER; 

    TYPE row_num IS TABLE OF xxwv_ap_token_test2.row_id%TYPE 
     INDEX BY BINARY_INTEGER; 

    ex_sql VARCHAR2 (2000); 
    t_num token_num; 
    r_num token_num; 
BEGIN 
    OPEN t_cur FOR ' SELECT token_number, row_id FROM ' 
        || p_source_table 
        || ' WHERE ROWNUM < 100'; 

    LOOP 
     FETCH t_cur 
     BULK COLLECT INTO t_num, r_num LIMIT p_commit_row; 

     ex_sql := 
      'UPDATE ' 
     || p_dest_table 
     || ' SET ' 
     || p_column_name 
     || ' = :1,token_flag = ''Y'' WHERE row_id = :2'; 
     FORALL i IN 1 .. t_num.COUNT 
     EXECUTE IMMEDIATE ex_sql 
        USING t_num (i), r_num (i); 
     COMMIT; 
     DBMS_OUTPUT.put_line ('commit finished'); 
     EXIT WHEN t_cur%NOTFOUND; 
    END LOOP; 

    CLOSE t_cur; 

    COMMIT; 
EXCEPTION 
    WHEN OTHERS 
    THEN 
     DBMS_OUTPUT.put_line ('Error occured while updating' || SQLERRM); 
END xxwv_cc_token_conversion;