oracle 批处理,bulk collect

这是一个示例,问了文心一言,给出的答复,最简单的demo

 

BEGIN
  -- 禁用日志
  EXECUTE IMMEDIATE 'ALTER SYSTEM SET events=''10046 trace name context off''';
 
  -- 执行你的批处理操作,比如插入或更新
  INSERT INTO your_table (column1, column2) VALUES (value1, value2);
  -- 或者
  UPDATE your_table SET column1 = value1 WHERE condition;
 
  -- 重新启用日志
  EXECUTE IMMEDIATE 'ALTER SYSTEM SET events=''10046 trace name context level 4''';
END;
/    



CREATE TABLE TBL_A (  
    column_1 VARCHAR2(100),  
    column_2 NUMBER,  
    column_3 DATE  
);  
  
CREATE TABLE TBL_B (  
    ID NUMBER PRIMARY KEY,  
    column_1 VARCHAR2(100),  
    column_2 NUMBER,  
    column_3 DATE  
);  
  
CREATE SEQUENCE SEQ_B START WITH 1 INCREMENT BY 1;


CREATE OR REPLACE PROCEDURE BULK_INSERT_FROM_A_TO_B IS  
    -- 定义用于批量收集的表类型  
    TYPE t_tbl_a_rows IS TABLE OF TBL_A%ROWTYPE INDEX BY PLS_INTEGER;  
    V_SOURCE_ROWS t_tbl_a_rows;  
      
    -- 定义一个用于存储TBL_B新ID的数组  
    TYPE t_ids IS TABLE OF TBL_B.ID%TYPE INDEX BY PLS_INTEGER;  
    v_ids t_ids;  
      
    -- 假设我们一次处理100条记录  
    v_limit CONSTANT PLS_INTEGER := 100;  
BEGIN  
    -- 使用BULK COLLECT批量从TBL_A中获取数据  
    SELECT * BULK COLLECT INTO V_SOURCE_ROWS FROM TBL_A WHERE ROWNUM <= v_limit;  
      
    -- 为每个记录分配ID  
    FOR i IN 1 .. V_SOURCE_ROWS.COUNT LOOP  
        v_ids(i) := SEQ_B.NEXTVAL;  
    END LOOP;  
      
    -- 批量插入到TBL_B  
    FORALL i IN 1 .. V_SOURCE_ROWS.COUNT  
        INSERT INTO TBL_B (ID, column_1, column_2, column_3)  
        VALUES (v_ids(i), V_SOURCE_ROWS(i).column_1, V_SOURCE_ROWS(i).column_2, V_SOURCE_ROWS(i).column_3);  
      
    -- 提交事务  
    COMMIT;  
      
    -- 可选:处理异常  
    EXCEPTION  
        WHEN OTHERS THEN  
            -- 回滚事务  
            ROLLBACK;  
            -- 抛出异常  
            RAISE;  
END BULK_INSERT_FROM_A_TO_B;  
/




CREATE OR REPLACE PROCEDURE BULK_INSERT_BY_YEAR IS  
    -- 定义记录类型以匹配TBL_A表的行  
    TYPE t_tbl_a_row IS RECORD (  
        column_1 VARCHAR2(100),  
        column_2 NUMBER,  
        month_num VARCHAR2(6)  
    );  
      
    -- 定义表类型以存储多个行  
    TYPE t_tbl_a_rows IS TABLE OF t_tbl_a_row INDEX BY PLS_INTEGER;  
    V_SOURCE_ROWS t_tbl_a_rows;  
      
    -- 遍历年份的游标  
    CURSOR c_years IS  
        SELECT DISTINCT SUBSTR(month, 1, 4) AS year  
        FROM TBL_A  
        ORDER BY year;  
      
    v_year TBL_A.month%TYPE;  
    v_sql_stmt VARCHAR2(4000);  
    v_id TBL_B_2023.ID%TYPE; -- 假设TBL_B_2023表有ID列,其他年份表类似  
BEGIN  
    -- 获取所有唯一的年份  
    OPEN c_years;  
    LOOP  
        FETCH c_years INTO v_year;  
        EXIT WHEN c_years%NOTFOUND;  
          
        -- 使用BULK COLLECT按年份收集数据  
        EXECUTE IMMEDIATE 'SELECT column_1, column_2, month FROM TBL_A WHERE SUBSTR(month, 1, 4) = :1'  
        BULK COLLECT INTO V_SOURCE_ROWS  
        USING v_year;  
          
        -- 为简化示例,假设所有表结构相同,且都有ID列作为主键  
        -- 实际情况中,您可能需要为每个表单独定义序列  
          
        -- 批量插入到对应的年份表  
        FOR i IN 1 .. V_SOURCE_ROWS.COUNT LOOP  
            -- 生成ID(这里简化为直接使用序列,但注意可能需要为每个年份表单独维护序列)  
            -- 假设所有年份表共享同一个序列SEQ_B,或者您有更复杂的逻辑来分配ID  
            v_id := SEQ_B.NEXTVAL;  
              
            -- 构建动态SQL语句以插入数据  
            v_sql_stmt := 'INSERT INTO TBL_B_' || v_year || ' (ID, column_1, column_2, month) VALUES (:1, :2, :3, :4)';  
              
            -- 执行动态SQL语句  
            EXECUTE IMMEDIATE v_sql_stmt  
            USING v_id, V_SOURCE_ROWS(i).column_1, V_SOURCE_ROWS(i).column_2, V_SOURCE_ROWS(i).month;  
        END LOOP;  
          
        -- 清除集合以准备下一次循环  
        V_SOURCE_ROWS.DELETE;  
    END LOOP;  
    CLOSE c_years;  
      
    -- 提交事务  
    COMMIT;  
      
    -- 异常处理(略)  
EXCEPTION  
    WHEN OTHERS THEN  
        -- 回滚事务  
        ROLLBACK;  
        -- 抛出异常或记录错误(这里只是简单回滚)  
        RAISE;  
END BULK_INSERT_BY_YEAR;  
/

 

posted on 2024-09-23 15:39  tomcat and jerry  阅读(22)  评论(0编辑  收藏  举报

导航