2013-04-29 3 views
3

мне нужно обновить таблицу А только 2 столбцов из таблицы B. (Таблицы A, B имеет только две колонки в общем - col1a, co11b :: col2a, col2bНужна помощь в обновлении 10 миллионов строк

Пример сценария: Я хотел, чтобы обновить все значения col1a с col1b где col2a = col2b

UPDATE a 
    SET col1a = (SELECT col1b 
        FROM b 
       WHERE a.col2a = b.col2b) 

Поскольку данные огромна, я хочу совершить строки через регулярные промежутки времени (скажем 5000 записей) вы можете предложить, пожалуйста..

+0

Вы можете использовать ключевое слово LIMIT или даже сделать свой собственный интервал, используя поле «ID», если вы получили один (1 <идентификатор <5000 [...]) – RelevantUsername

+7

10 миллионов строк не так много данных в эти дни. Почему вы хотите совершать интервалы? Это, как минимум, сделает вещи медленнее. И для этого потребуется еще немного кода. И он будет генерировать больше 'UNDO' и' REDO'. Вы действительно уверены, что это то, что вы хотите сделать? –

+0

Я должен совершать через равные промежутки времени. Но не уверен в том, что строка no совершает. Это входной параметр процедуры. Я должен зафиксировать на основе входного параметра. –

ответ

0

Если вы хотите и, если возможно, e в вашей среде, вы можете

create table newtable as select .... from oldtable 

которое создаст новый стол.

Затем воссоздайте индексы, переименуйте две таблицы и заново создайте ограничения.

+0

Это имеет смысл, но все же создает и удаляет потом: D +1 – 2013-04-30 03:00:11

4

Поскольку запрос, который вы указали в вопросе, содержит подзапрос, он выполняет поиск в таблице b для каждой обновляемой строки. Это может быть медленным, и обновление все равно достаточно медленное.

В зависимости от дизайна ваших таблиц, я бы попытался «ОБНОВИТЬ вид» или MERGE. Способность к UPDATE зависит от наличия «ключа-сохраненного соединения». Если у вас этого нет, UPDATE не будет работать. Трудно дать правильный ответ без какого-либо DDL для таблиц.

UPDATE (
    select col1a, col1b, col2a, col2b 
    from 
    a join b on (a.col2a = b.col2b) 
) 
set col1a = col1b; 

Если UPDATE не работает, вы можете попробовать MERGE. Это должно работать в большем количестве случаев, чем обновление.

merge into a 
using b on (a.col2a = b.col2b) 
when matched then update set a.col1a = b.col1b 

Преимущество обоих этих утверждений состоит в том, что они работают на весь набор данных, а не обновляются по одной строке за раз. Это может быть трудно получить обновление для выполнения хорошо.

Возможно, стоит удалить любые индексы на столбце col1a, если они есть.

+0

Единственное предостережение, которое я бы упомянул в инструкции 'MERGE', состоит в том, что для него требуется предложение' WHEN NOT MATCHED' с инструкцией 'INSERT', поэтому возможно, не лучший выбор в этом случае. Тем не менее, я согласен с тем, что удаление индексов на 'col1a' было бы хорошим, так как это могло бы устранить любые ограничения, поскольку это может ускорить обновления. –

+0

@MauriceReeves Я думал, что предложение 'INSERT' тоже требуется, но, похоже, было необязательным, когда я смотрел документацию 10r2, и SQL Fiddle не жаловался, когда я ее покидал. –

+0

Странно. Когда я построил инструкции MERGE на Oracle 11g, я получил жалобы на отсутствующие предложения и т. Д., Когда я не включил 'INSERT'. Удивление, если 10r2 был более прощающим .... –

1

Спасибо всем. Я получил решение. Я искал решение, как показано ниже

 CREATE OR REPLACE PROCEDURE xxwv_cc_token_conversion (
    p_source_table IN VARCHAR2, 
    p_dest_table  IN VARCHAR2, 
    p_column_name IN VARCHAR2, 
    p_commit_row  IN NUMBER 
) 
IS 
    TYPE cv_typ IS REF CURSOR; 

    t_cur cv_typ; 

    TYPE token_num IS TABLE OF xxwv_ap_token_test2.token_number%TYPE 
     INDEX BY BINARY_INTEGER; 

    TYPE row_num IS TABLE OF xxwv_ap_token_test2.row_id%TYPE 
     INDEX BY BINARY_INTEGER; 

    ex_sql VARCHAR2 (2000); 
    t_num token_num; 
    r_num token_num; 
BEGIN 
    OPEN t_cur FOR ' SELECT token_number, row_id FROM ' 
        || p_source_table 
        || ' WHERE ROWNUM < 100'; 

    LOOP 
     FETCH t_cur 
     BULK COLLECT INTO t_num, r_num LIMIT p_commit_row; 

     ex_sql := 
      'UPDATE ' 
     || p_dest_table 
     || ' SET ' 
     || p_column_name 
     || ' = :1,token_flag = ''Y'' WHERE row_id = :2'; 
     FORALL i IN 1 .. t_num.COUNT 
     EXECUTE IMMEDIATE ex_sql 
        USING t_num (i), r_num (i); 
     COMMIT; 
     DBMS_OUTPUT.put_line ('commit finished'); 
     EXIT WHEN t_cur%NOTFOUND; 
    END LOOP; 

    CLOSE t_cur; 

    COMMIT; 
EXCEPTION 
    WHEN OTHERS 
    THEN 
     DBMS_OUTPUT.put_line ('Error occured while updating' || SQLERRM); 
END xxwv_cc_token_conversion; 
Смежные вопросы