2013-11-04 21 views
0

我是pl/sql的新手,需要在數據庫中進行大量更新。超過400萬個條目必須更改,我希望在每更新一次5.000之後執行一次提交。我很迷茫,無法做到這一點。在大型更新查詢中執行定期提交

在這裏我的查詢。

update accounts a set a.validateid = 'TH20381', flagexport = 25, exportname ='zde' 
where a.accountnumber >= 35026879 and a.ownerid like 'V35%'; 

在此先感謝。

+1

爲什麼你想這樣做?頻繁提交只會讓整個事情變得更慢,而不是更快。順便說一句:在你的例子中,沒有任何PL/SQL。 PL/SQL僅用於**存儲過程。 –

+0

我不想過度使用UNDO表空間。並且避免系統崩潰嘗試執行400萬次更新,如果更新編號爲2k時出現錯誤,則可以完成或不執行所有更新。 –

+0

在sql服務器中,我們使用一次循環處理x個記錄來完成此操作。通常我使用臨時表,然後更新我已處理的臨時表,然後選擇臨時表中更新位爲空的下一個5000。然後循環直到完成。不確定這是否是Oracle中最好的方式。 – HLGEM

回答

2

如果你真的需要這樣做,你可以考慮使用DBMS_PARALLEL_EXECUTE包。這裏有一個例子它會是什麼樣子:

DECLARE 
    v_sql VARCHAR2(4000); 
BEGIN 
    -- create the task 
    DBMS_PARALLEL_EXECUTE.create_task (task_name => 'update_accounts_task'); 

    -- define how the task should be split 
    DBMS_PARALLEL_EXECUTE.create_chunks_by_rowid(task_name => 'update_accounts_task', 
               table_owner => 'YOUR_USERNAME', 
               table_name => 'ACCOUNTS', 
               by_row  => true, 
               chunk_size => 5000); 

    -- command to be split and executed - notice the condition on rowid 
    -- which is required since we defined above that the task should be split 
    -- by rowid 
    v_sql := 'UPDATE accounts 
       SET validateid = ''TH20381'', 
        flagexport = 25, 
        exportname = ''zde'' 
       WHERE accountnumber >= 35026879 
       AND ownerid LIKE ''V35%'' 
       AND rowid BETWEEN :start_id AND :end_id'; 

    -- run the task 
    DBMS_PARALLEL_EXECUTE.run_task(task_name  => 'update_accounts_task', 
           sql_stmt  => v_sql, 
           language_flag => DBMS_SQL.NATIVE, 
           parallel_level => 10); 
END; 

用戶創建的任務必須被賦予特權CREATE JOB

根據蒂姆霍爾的文章可訪問這裏:DBMS_PARALLEL_EXECUTE at Oracle Base

+0

@RenéNyffenegger我沒有說它更優雅,只是爲作者的問題提供了一個可能的解決方案。 –