按块插入

时间:2018-08-29 15:03:44

标签: oracle plsql

我正在尝试使用insert into语句,但收到错误消息:

  

ORA-01628:回滚段_SYSSMU134_1882489978 $已达到最大#个范围(32765)

增加UNDO表空间不是一种选择,因此我想一种按块(例如,一次有100万行)插入这些数据的方法。有人可以以这种方式帮助重写此过程吗?

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 :(得分:0)

基本上,我能够以动态查询的方式跳过过程内部的整个块方法,就像这样:

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;