我想将一个列数据复制到包含10百万条记录的大表中的另一列中。 我使用sys refcursor将数据从一列复制到另一列。复制数据需要30多分钟。我使用的是ORACLE 11gR2。
还有其他方法可以做同样的事。以下是脚本
CREATE OR REPLACE PROCEDURE tblCursor(org_mig OUT SYS_REFCURSOR)
IS
BEGIN
OPEN org_mig FOR
select id from tbl;
END;
/
DECLARE
org_mig SYS_REFCURSOR;
t_id organization.id%TYPE;
loop_var number(10);
commit_interval number(10);
BEGIN
loop_var :=1;
commit_interval:=10000;
tblCursor(org_mig);
LOOP
FETCH org_mig INTO t_id;
EXIT WHEN org_mig%NOTFOUND;
update tbl set col1=col2 where id=t_id;
IF mod(loop_var,commit_interval)=0 THEN
Commit;
End if;
loop_var :=loop_var+1;
END LOOP;
Commit;
CLOSE org_mig;
END;
/
答案 0 :(得分:1)
你在tbl
的每一行都这样做,对吗?如果是这样,你应该这样做:
update tbl
set col1 = col2
/
更新一千万行需要一些时间,但是设置操作方式比你实现的Row By Agonizing Row方法更快。另外,批量提交这样的提交是不好的做法。它不仅会减慢速度,而且会导致ORA-01555: Snapshot too old
例外。 Find out more
答案 1 :(得分:0)
Still it has been taken long time to update.
I am trying with different one but getting error.
-----------------------------------
Error starting at line : 43 in command -
SELECT *
FROM TABLE(test_parallel_update(CURSOR(SELECT * FROM organization)))
Error report -
SQL Error: ORA-12801: error signaled in parallel query server P003
ORA-00932: inconsistent datatypes: expected - got -
ORA-06512: at "QA249.TEST_PARALLEL_UPDATE", line 21
12801. 00000 - "error signaled in parallel query server %s"
*Cause: A parallel query server reached an exception condition.
*Action: Check the following error message for the cause, and consult
your error manual for the appropriate action.
*Comment: This error can be turned off with event 10397, in which
case the server's actual error is signaled instead.
---------------------------
Here is the script:
CREATE OR REPLACE TYPE test_num_arr AS TABLE OF NUMBER;
CREATE OR REPLACE FUNCTION test_parallel_update (
test_cur IN SYS_REFCURSOR
)
RETURN test_num_arr
PARALLEL_ENABLE (PARTITION test_cur BY ANY)
PIPELINED
IS
PRAGMA AUTONOMOUS_TRANSACTION;
test_rec organization%ROWTYPE;
TYPE num_tab_t IS TABLE OF NUMBER(10,0);
TYPE vc2_tab_t IS TABLE OF number(1,0);
id NUM_TAB_T;
org_type_old NUM_TAB_T;
IS_DELETED_old VC2_TAB_T;
cnt INTEGER := 0;
BEGIN
LOOP
FETCH test_cur BULK COLLECT INTO id, org_type_old, IS_DELETED_old LIMIT 1000;
EXIT WHEN id.COUNT() = 0;
FORALL i IN id.FIRST .. id.LAST
UPDATE organization
SET org_type = org_type_old(i)
, IS_DELETED = IS_DELETED_old(i)
WHERE id = id(i);
cnt := cnt + id.COUNT;
END LOOP;
CLOSE test_cur;
COMMIT;
PIPE ROW(cnt);
RETURN;
END;
/
show error;
---- To Execute ----
SELECT *
FROM TABLE(test_parallel_update(CURSOR(SELECT * FROM organization)));
Note:
Table
organization
(
id number(10,0),
org_type number(10,0),
org_type_old number(10,0),
IS_DELETED number(1,0),
IS_DELETED_OLD number(1,0)
);
where id is a primary key, Now I want copy org_type_old and IS_DELETED_OLD into org_type and IS_DELETED respectively.