Вставить в куски - PullRequest
       1

Вставить в куски

0 голосов
/ 29 августа 2018

Я пытаюсь использовать оператор insert into, но получаю ошибку:

ORA-01628: достигнуто максимальное количество экстентов (32765) для сегмента отката _SYSSMU134_1882489978 $

Увеличение табличного пространства UNDO не вариант, поэтому я хотел бы добавить способ вставки этих данных кусками (например, с 1 миллионом строк за раз). Может ли кто-нибудь помочь переписать эту процедуру таким образом?

CREATE OR REPLACE PROCEDURE create_chunks (
  p_source_table IN VARCHAR2,
  p_table_name_chunk IN VARCHAR2,
  p_chunks IN VARCHAR2
) AS
v_insert_sql CLOB;
BEGIN
  v_insert_sql := 'INSERT INTO ' || p_table_name_chunk ||
    ' (rid, chunk_number) ' ||
    'SELECT /*+ parallel(64) */ rowid rid,' ||
      'mod( ora_hash(rowid), :p_chunks ) as chunk_number '
    'FROM ' || p_source_table;
   EXECUTE IMMEDIATE v_insert_sql USING p_chunks;
   COMMIT;
END;

Этот v_insert_sql не работает с вышеупомянутой ошибкой. У меня есть рабочее решение с использованием курсора, подобного так:

DECLARE
  CURSOR v_cur IS SELECT /*+ parallel(64) */
    rowid rid, mod( ora_hash(rowid), 20000 ) AS chunk_number
  -- I need this table to be parametric name
  FROM some_table;
  TYPE t_sample IS TABLE OF v_cur%ROWTYPE;
  v_sample t_sample;
  v_row_limit CONSTANT NUMBER := 1000000;
BEGIN
  OPEN v_cur;
  LOOP
    FETCH v_cur BULK COLLECT INTO v_sample LIMIT v_row_limit;
    FORALL i IN v_sample.first .. v_sample.last
      INSERT INTO chunk_table VALUES v_sample(i);
    COMMIT;
    EXIT WHEN v_cur%NOTFOUND;
  END LOOP;
  CLOSE v_cur;
END;

Я не могу переместить этот курсор прямо в процедуру, так как имя таблицы меняется, и мне нужно, чтобы оно было параметрическим, так как при использовании курсора мне приходится повторять один и тот же код для разных таблиц. Так что вопрос в том, как с этим бороться?

1 Ответ

0 голосов
/ 06 сентября 2018

По сути, я смог просто пропустить весь подход к фрагментам внутри процедуры как динамический запрос, например:

CREATE OR REPLACE PROCEDURE create_chunks (
  p_source_table IN VARCHAR2,
  p_table_name_chunk IN VARCHAR2,
  p_chunks IN VARCHAR2
) AS
  v_insert_sql CLOB;
BEGIN
  v_insert_sql := '' ||
    ' DECLARE ' || CHR(10) ||
    ' CURSOR cur1 IS SELECT ' || CHR(10) ||
    '   /*+ parallel(64) full(tbn)*/ rowid rid,' || CHR(10) ||
    '   mod( ora_hash(rowid), :p_chunks ) AS chunk_number' || CHR(10) ||
    ' FROM ' || p_source_table || ' tbn;' || CHR(10) ||
    ' TYPE t_sample IS TABLE OF cur1%ROWTYPE;' || CHR(10) ||
    ' v_sample t_sample;' || CHR(10) ||
    ' v_row_limit CONSTANT NUMBER := 1000000;' || CHR(10) ||
    ' BEGIN' || CHR(10) ||
    '   OPEN cur1;' || CHR(10) ||
    '   LOOP' || CHR(10) ||
    '     FETCH cur1 BULK COLLECT INTO v_sample LIMIT v_row_limit;' || CHR(10) ||
    '     FORALL i IN v_sample.first .. v_sample.last' || CHR(10) ||
    '       INSERT INTO ' || p_table_name_chunk || ' VALUES v_sample(i);' || CHR(10) ||
    '     COMMIT;' || CHR(10) ||
    '     EXIT WHEN cur1%NOTFOUND;' || CHR(10) ||
    '   END LOOP;' || CHR(10) ||
    '   CLOSE cur1;' || CHR(10) ||
    ' END;';
  EXECUTE IMMEDIATE v_insert_sql USING p_chunks;
  COMMIT;
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...