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;