2015-06-25 133 views
0

我在我的java程序中使用下面的函數將臨時表中的列複製到主表中。PLSQL循環提交更新

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運行的batch_size,對於每個提交100000個記錄有作爲id_col我用上面是主鍵進行更新。在運行java程序之後,在我檢查主表中的更新的時候,我能夠看到類似正在更新的批次6469或80148的記錄。

臨時表中大約有1000萬條記錄。如果我刪除了所有更新語句,我正在以適當的批處理大小遍歷數據。

可以在任何澄清我對爲什麼發生這種情況

回答

0

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; 
+0

我試過光標也。我遇到的問題不是迭代,而是更新。對於臨時表中的所有記錄,主表中有一條記錄。當我檢查更新的記錄數仍然不等於我的batch_size的倍數。 –

+0

例如BATCH_SIZE = 10 迭代1 offset = 0,max_result = 10; 迭代2 offset = 10,max_result = 20; select seg(從級別<1000的雙連接中選擇級別seg),其中seg在0和10之間; select seg(從級別<1000的雙連接中選擇級別seg),其中seg在10和20之間; 檢查結果。 –

0
-- 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;