Oracle-使用游标循环进行批量更新
我想在这样一张桌子上的一张大桌子上执行更新(我现在认为这不是最佳做法): 目标:Oracle-使用游标循环进行批量更新,oracle,plsql,bulkupdate,Oracle,Plsql,Bulkupdate,我想在这样一张桌子上的一张大桌子上执行更新(我现在认为这不是最佳做法): 目标:updatetarget\u表set NET=VAT,VAT=NET 我提出了一个批量更新,但在第43行我得到了一个ORA-00913:“对许多值”,我无法解释。此外,我不知道如何在该变体中同时更新两行。 有人能帮忙吗 DECLARE -- new data CURSOR new_data_cur IS select a.rowid,
updatetarget\u表set NET=VAT,VAT=NET
我提出了一个批量更新,但在第43行我得到了一个ORA-00913:“对许多值”,我无法解释。此外,我不知道如何在该变体中同时更新两行。
有人能帮忙吗
DECLARE
-- new data
CURSOR new_data_cur IS
select
a.rowid,
a.TICKET_ID,
a.product_id,
b.NET,
b.VAT
from TARGET_TABLE a
join TARGET_TABLE_COPY b
on ( a.TICKET_ID=b.TICKET_ID AND a.product_id =b.product_id ) ;
TYPE new_data_type IS TABLE OF new_data_cur%rowtype INDEX BY PLS_INTEGER;
new_data_tab new_data_type;
TYPE row_id_type IS TABLE OF ROWID INDEX BY PLS_INTEGER;
row_id_tab row_id_type;
TYPE rt_update_cols IS RECORD (
NET TARGET_TABLE.NET%TYPE
-- VAT TARGET_TABLE.VAT%TYPE
);
TYPE update_cols_type IS
TABLE OF rt_update_cols INDEX BY PLS_INTEGER;
update_cols_tab1 update_cols_type;
--update_cols_tab2 update_cols_type;
dml_errors EXCEPTION;
PRAGMA exception_init ( dml_errors,-24381 );
BEGIN
OPEN new_data_cur;
LOOP
FETCH new_data_cur BULK COLLECT INTO new_data_tab LIMIT 50000;
EXIT WHEN new_data_tab.count=0;
FOR i IN new_data_tab.first..new_data_tab.last LOOP
row_id_tab(i) := new_data_tab(i).rowid;
update_cols_tab1(i).NET := new_data_tab(i).VAT;
-- update_cols_tab2(i).VAT := new_data_tab(i).NET;
END LOOP;
FORALL i IN new_data_tab.first..new_data_tab.last SAVE EXCEPTIONS # ORA-00913: To many values
UPDATE TARGET_TABLE
-- SET row = update_cols_tab(i)
SET row = update_cols_tab1(i)
-- row = update_cols_tab2(i)
WHERE ROWID = row_id_tab(i);
COMMIT;
EXIT WHEN new_data_tab.count=0;
END LOOP;
COMMIT;
CLOSE new_data_cur;
EXCEPTION
WHEN dml_errors THEN
FOR i IN 1..SQL%bulk_exceptions.count LOOP
dbms_output.put_line('Some error occured');
END LOOP;
END;
我相信在交换值时不需要额外的光标
FOR i IN new_data_tab.first..new_data_tab.last LOOP
row_id_tab(i) := new_data_tab(i).rowid;
update_cols_tab1(i).NET := new_data_tab(i).VAT;
-- update_cols_tab2(i).VAT := new_data_tab(i).NET;
END LOOP;
因此,您的代码将在批量更新中使用这些值
DECLARE
-- new data
CURSOR new_data_cur IS
select
a.rowid,
a.TICKET_ID,
a.product_id,
b.NET,
b.VAT
from TARGET_TABLE a
join TARGET_TABLE_COPY b
on ( a.TICKET_ID=b.TICKET_ID AND a.product_id =b.product_id ) ;
TYPE new_data_type IS TABLE OF new_data_cur%rowtype INDEX BY PLS_INTEGER;
new_data_tab new_data_type;
TYPE row_id_type IS TABLE OF ROWID INDEX BY PLS_INTEGER;
row_id_tab row_id_type;
TYPE rt_update_cols IS RECORD (
NET TARGET_TABLE.NET%TYPE
-- VAT TARGET_TABLE.VAT%TYPE
);
TYPE update_cols_type IS
TABLE OF rt_update_cols INDEX BY PLS_INTEGER;
update_cols_tab1 update_cols_type;
--update_cols_tab2 update_cols_type;
dml_errors EXCEPTION;
PRAGMA exception_init ( dml_errors,-24381 );
BEGIN
OPEN new_data_cur;
LOOP
FETCH new_data_cur BULK COLLECT INTO new_data_tab LIMIT 50000;
EXIT WHEN new_data_tab.count=0;
FORALL i IN new_data_tab.first..new_data_tab.last SAVE EXCEPTIONS # ORA-00913: To many values
UPDATE TARGET_TABLE
-- SET row = update_cols_tab(i)
-- SET row = update_cols_tab1(i)
-- row = update_cols_tab2(i)
NET = update_cols_tab1(i).VAT
VAT = update_cols_tab1(i).NET
WHERE ROWID = row_id_tab(i);
COMMIT;
EXIT WHEN new_data_tab.count=0;
END LOOP;
COMMIT;
CLOSE new_data_cur;
EXCEPTION
WHEN dml_errors THEN
FOR i IN 1..SQL%bulk_exceptions.count LOOP
dbms_output.put_line('Some error occured');
END LOOP;
END;
你为什么这样做,当你可以只做
updatetarget\u TABLE set NET=VAT,VAT=NET代码>?>500.000.000记录SSO?在单个update语句中更新表仍然比批量更新更快。或者,您可以尝试重命名列(net->net\u-vat,vat->net,net\u-vat->vat)。但是,如果不在生产代码中指定要插入的列列表,则假定不会选择*
或插入到target_表中。但是,如果绝对需要,您可以使用dbms_重新定义对列进行潜在的重新排序。或者,您可以临时添加一列UP2DATE INTEGER DEFAULT 0
,然后执行UPDATE TARGET_TABLE set NET=VAT,VAT=NET,UP2DATE=1其中UP2DATE=0和ROWNUM<10000
以按区块更新数据。。。
DECLARE
-- new data
CURSOR new_data_cur IS
select
a.rowid,
a.TICKET_ID,
a.product_id,
b.NET,
b.VAT
from TARGET_TABLE a
join TARGET_TABLE_COPY b
on ( a.TICKET_ID=b.TICKET_ID AND a.product_id =b.product_id ) ;
TYPE new_data_type IS TABLE OF new_data_cur%rowtype INDEX BY PLS_INTEGER;
new_data_tab new_data_type;
TYPE row_id_type IS TABLE OF ROWID INDEX BY PLS_INTEGER;
row_id_tab row_id_type;
TYPE rt_update_cols IS RECORD (
NET TARGET_TABLE.NET%TYPE
-- VAT TARGET_TABLE.VAT%TYPE
);
TYPE update_cols_type IS
TABLE OF rt_update_cols INDEX BY PLS_INTEGER;
update_cols_tab1 update_cols_type;
--update_cols_tab2 update_cols_type;
dml_errors EXCEPTION;
PRAGMA exception_init ( dml_errors,-24381 );
BEGIN
OPEN new_data_cur;
LOOP
FETCH new_data_cur BULK COLLECT INTO new_data_tab LIMIT 50000;
EXIT WHEN new_data_tab.count=0;
FORALL i IN new_data_tab.first..new_data_tab.last SAVE EXCEPTIONS # ORA-00913: To many values
UPDATE TARGET_TABLE
-- SET row = update_cols_tab(i)
-- SET row = update_cols_tab1(i)
-- row = update_cols_tab2(i)
NET = update_cols_tab1(i).VAT
VAT = update_cols_tab1(i).NET
WHERE ROWID = row_id_tab(i);
COMMIT;
EXIT WHEN new_data_tab.count=0;
END LOOP;
COMMIT;
CLOSE new_data_cur;
EXCEPTION
WHEN dml_errors THEN
FOR i IN 1..SQL%bulk_exceptions.count LOOP
dbms_output.put_line('Some error occured');
END LOOP;
END;