需要帮助,我需要从表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值。
需要帮助,我需要从表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值。
如果你想和如果可能在你的环境中,你可以
create table newtable as select .... from oldtable
这将创建一个新表。
然后重新创建索引,重命名这两个表并重新创建约束。
这是有道理的,但仍然在创建和删除之后:D +1 – 2013-04-30 03:00:11
由于您在问题中显示的查询包含子查询,因此会对正在更新的每一行在表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
列中的任何索引。
我只提到'MERGE'语句的唯一警告是它需要'WHEN NOT MATCHED'子句和'INSERT'语句,所以它在这种情况下可能不是最好的选择。然而,我确实认为删除'col1a'上的索引将是很好的,因为可以消除任何限制,因为这可以加速更新。 – 2013-04-30 03:06:53
@MauriceReeves我认为'INSERT'子句也是必需的,但是当我查看10r2文档时SQL似乎是可选的,而SQL小提琴在我离开时没有抱怨。 – 2013-04-30 03:26:48
奇怪。当我在Oracle 11g上建立'MERGE'语句时,当我没有包含'INSERT'时,我收到了关于丢失子句的抱怨等。想知道10r2是否更加宽容...... – 2013-04-30 04:03:57
谢谢大家。我得到了解决方案。 我一直在寻找的解决方案类似下面
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;
您可以使用LIMIT关键字,甚至做用,如果你拿到“身份证”字段中输入您自己的时间间隔一(1
RelevantUsername
2013-04-29 21:27:08
这几天1000万行数据并不多。你为什么要间隔提交?这至少会让事情变得更慢。这将需要更多的代码。它会产生更多的“UNDO”和“REDO”。你确定这就是你想要做的? – 2013-04-29 21:32:01
我必须定期提交。但不确定在要提交的行号上。 它是过程的输入参数。 我必须根据输入参数提交。 – 2013-04-29 21:44:35