有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用于更新的PLSQL循环中的java提交

我在java程序中使用下面的函数将一列从临时表复制到主表

FUNCTION TEST(TBL_NAME VARCHAR2, TMP_TBL_NAME VARCHAR2, ID_COL VARCHAR2, REQ_COL VARCHAR2, BATCH_SIZE NUMBER) RETURN NUMBER AS
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM ' || TMP_TBL_NAME INTO TOTAL_RECORDS;
OFFSET := 0;
WHILE OFFSET < TOTAL_RECORDS
LOOP
  MAX_RESULTS := OFFSET + BATCH_SIZE;
  EXECUTE IMMEDIATE 'SELECT ' || ID_COL || ', ' || REQ_COL || ' FROM ' || TMP_TBL_NAME || ' WHERE SEQ_NBR BETWEEN :OFFSET AND :MAX_RESULTS' BULK COLLECT INTO SEQ_IDS, REQ_COL_VALUESS USING OFFSET, MAX_RESULTS;
  FORALL IND IN SEQ_IDS.FIRST .. SEQ_IDS.LAST
    EXECUTE IMMEDIATE 'UPDATE ' || TBL_NAME || ' SET ' || REQ_COL || ' = :REQ_COL_VAL WHERE ' || ID_COL || ' = :ID_COL_VAL' USING REQ_COL_VALUESS(IND), SEQ_IDS(IND);
  OFFSET := MAX_RESULTS;
  COMMIT;
END LOOP;
RETURN 0;
EXCEPTION
WHEN OTHERS THEN
  RAISE CUST_EXCEPTION; 
END;

预期结果是,当我以100000的批大小运行时,每次提交100000条记录都必须更新,因为我上面使用的id列是主键。在运行java程序之后,在检查主表中的更新时,我能够看到像这样的批次6469或80148的记录正在更新

temp表中大约有1000万条记录。如果我删除forall update语句,我将以适当的批大小对数据进行迭代

有什么能澄清我为什么会这样吗


共 (2) 个答案

  1. # 1 楼答案

      first iteration offset= 0 , max_result = 10 
      v_batch_size = 10
      offset := 0 
       MAX_RESULTS := 10 
    select seg from ( Select level seg from dual connect by level < 1000)  where seg between 0 and 10;
      secound iteration 
      v_batch_size = 10
      offset := 10 
       MAX_RESULTS := 20 
    select seg from ( Select level seg from dual connect by level < 1000) where seg between 10 and 20;
    
  2. # 2 楼答案

    1)临时表中有多少条记录

    2)为什么不使用sys_refcursor和带限制的批量收集

    declare 
     v_cursor sys_refcursor; 
     res1 sys.DBMS_DEBUG_VC2COLL;   - predefined collection in oracle 
     res2 sys.DBMS_DEBUG_VC2COLL;
     v_batch_size pls_integer := 50;
    begin 
     open v_cursor for 'Select 1,2 from dual connect by level < 10000';
     loop
     fetch v_cursor bulk collect into res1,res2 limit v_batch_size;
     exit when res1.count =0;
        dbms_output.put_line(res1.count);
        forall ind in res1.first .. res1.last loop e.g 
        commit;
     end loop;
      close v_cursor;
    end;