ORACLE中如何批量重置序列

背景:

数据库所有序列都重置为1了,所以要将所有的序列都更新为对应的表主键(这里是id)的最大值+1。我这里序列的规则是SEQ_表名。


BEGIN
  ENHANCED_SYNC_SEQUENCES('WJ_CPP'); -- 替换为你的模式名
END;
/
CREATE OR REPLACE PROCEDURE ENHANCED_SYNC_SEQUENCES(p_schema_name IN VARCHAR2) IS
  v_table_name VARCHAR2(30);
  v_seq_name VARCHAR2(30);
  v_max_id NUMBER;
  v_new_seq_value NUMBER;
  v_current_seq_value NUMBER;
  v_increment_by NUMBER;
  v_table_exists NUMBER;
  v_step VARCHAR2(100); -- 记录当前执行步骤,便于排查
  
  CURSOR c_sequences IS
    SELECT sequence_name
    FROM all_sequences
    WHERE sequence_owner = UPPER(p_schema_name)
      AND sequence_name LIKE 'SEQ\_%' ESCAPE '\';
BEGIN
  DBMS_OUTPUT.PUT_LINE('=== 开始处理模式: ' || UPPER(p_schema_name) || ' ===');
  
  FOR seq_rec IN c_sequences LOOP
    v_seq_name := seq_rec.sequence_name;
    DBMS_OUTPUT.PUT_LINE(CHR(10) || '--- 处理序列: ' || v_seq_name || ' ---');
    
    -- 步骤1: 提取表名
    v_step := '提取表名';
    v_table_name := SUBSTR(v_seq_name, 5);
    DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 对应表名 -> ' || v_table_name);
    
    -- 步骤2: 检查表是否存在
    v_step := '检查表是否存在';
    SELECT COUNT(*) INTO v_table_exists
    FROM all_tables
    WHERE owner = UPPER(p_schema_name)
      AND table_name = UPPER(v_table_name);
      
    IF v_table_exists = 0 THEN
      DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 警告 - 表不存在,跳过');
      CONTINUE;
    END IF;
    DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 表存在');
    
    -- 步骤3: 检查ID列是否存在
    v_step := '检查ID列是否存在';
    DECLARE
      v_id_exists NUMBER;
    BEGIN
      SELECT COUNT(*) INTO v_id_exists
      FROM all_tab_columns
      WHERE owner = UPPER(p_schema_name)
        AND table_name = UPPER(v_table_name)
        AND column_name = 'ID';
        
      IF v_id_exists = 0 THEN
        DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 警告 - 无ID列,跳过');
        CONTINUE;
      END IF;
    END;
    DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: ID列存在');
    
    -- 步骤4: 查询表最大ID
    v_step := '查询表最大ID';
    BEGIN
      EXECUTE IMMEDIATE 'SELECT NVL(MAX(ID), 0) FROM ' || p_schema_name || '.' || v_table_name
        INTO v_max_id;
      v_new_seq_value := v_max_id + 1;
      DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 表最大ID=' || v_max_id || ', 目标序列值=' || v_new_seq_value);
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 错误 - ' || SQLERRM);
        CONTINUE;
    END;
    
    -- 步骤5: 获取序列当前值
    v_step := '获取序列当前值';
    BEGIN
      EXECUTE IMMEDIATE 'SELECT ' || p_schema_name || '.' || v_seq_name || '.NEXTVAL FROM DUAL'
        INTO v_current_seq_value;
      DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 序列当前值=' || v_current_seq_value);
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 错误 - ' || SQLERRM);
        CONTINUE;
    END;
    
    -- 步骤6: 判断是否需要调整
    v_step := '判断是否需要调整';
    IF v_current_seq_value >= v_new_seq_value THEN
      DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 无需调整(当前值 >= 目标值)');
      CONTINUE;
    END IF;
    DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 需要调整(当前值 < 目标值)');
    
    -- 步骤7: 调整序列
    v_step := '调整序列';
    BEGIN
      -- 计算增量
      v_increment_by := v_new_seq_value - v_current_seq_value;
      DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 临时增量=' || v_increment_by);
      
      -- 修改增量
      EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || p_schema_name || '.' || v_seq_name || ' INCREMENT BY ' || v_increment_by;
      
      -- 触发增量
      EXECUTE IMMEDIATE 'SELECT ' || p_schema_name || '.' || v_seq_name || '.NEXTVAL FROM DUAL' INTO v_current_seq_value;
      DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 调整后的值=' || v_current_seq_value);
      
      -- 恢复增量
      EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || p_schema_name || '.' || v_seq_name || ' INCREMENT BY 1';
      DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 恢复增量为1,处理成功');
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 错误 - ' || SQLERRM);
        -- 尝试恢复增量
        BEGIN
          EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || p_schema_name || '.' || v_seq_name || ' INCREMENT BY 1';
        EXCEPTION
          WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('步骤[' || v_step || ']: 恢复增量失败 - ' || SQLERRM);
        END;
        CONTINUE;
    END;
  END LOOP;
  
  DBMS_OUTPUT.PUT_LINE(CHR(10) || '=== 所有序列处理完毕 ===');
END ENHANCED_SYNC_SEQUENCES;
/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值