Oracle 在12C中重新创建序列

Oracle 在12C中重新创建序列,oracle,Oracle,我们正在将我们的系统从Oracle 11g迁移到12C,我的场景只涉及测试,当我们上线时,我们将暂停应用程序,这样就不会生成更多的序列。我对甲骨文也是新手 在我们的测试环境中,由于序列号落后,我们得到了密钥冲突 我需要循环浏览343个现有序列,获得最大数量的序列,并从每个表中当前最大数量+1开始重建/重新创建序列。下面来自另一个线程的代码可能可以工作,但我需要它在343个表之间循环。从11g中的用户_序列中获取最大序列号 declare ex number; be

我们正在将我们的系统从Oracle 11g迁移到12C,我的场景只涉及测试,当我们上线时,我们将暂停应用程序,这样就不会生成更多的序列。我对甲骨文也是新手

在我们的测试环境中,由于序列号落后,我们得到了密钥冲突

我需要循环浏览343个现有序列,获得最大数量的序列,并从每个表中当前最大数量+1开始重建/重新创建序列。下面来自另一个线程的代码可能可以工作,但我需要它在343个表之间循环。从11g中的用户_序列中获取最大序列号

     declare
      ex number;
     begin
      select MAX(MAX_FK_ID)  + 1 into ex from TABLE;
       If ex > 0 then
        begin
                execute immediate 'DROP SEQUENCE SQ_NAME';
           exception when others then
             null;
        end;
        execute immediate 'CREATE SEQUENCE SQ_NAME INCREMENT BY 1 START 
        WITH ' || ex || ' NOCYCLE CACHE 20 NOORDER';
       end if;
    end;

若您在应用程序停止运行时导出数据,然后将数据导入12c,那个么您就不会有关键问题

如果升级12c到位,您也不应该有关键问题


我参与过几十次12c迁移,从未听说过这个问题。

这就是有一个合适的命名约定/标准的地方

在我设计的数据库中,每个表都有一个3或4个字符的别名,我们用这个别名命名索引、约束等

如果名为_table的表具有别名ttab,则主键列将是ttab_id,主键约束将是pk_ttab,用于ttab_id的序列将是seq_ttab_id

考虑到这一点,您可能会编写以下未经测试的人,因此可能需要进行一些调整,但希望您能够了解总体思路:

DECLARE
   CURSOR cseq IS
      SELECT sequence_name seqname FROM user_sequences;
   tabname VARCHAR2(30);
   colname VARCHAR2(30);
   cmd     VARCHAR2(1000);
   maxval  NUMBER;
BEGIN
   FOR r IN cseq LOOP
      /*
      ** Now get corresponding table/column name matching the sequence name
      */
      SELECT table_name, column_name 
      INTO tabname, colname
      FROM user_cons_columns #
      WHERE column_name = REPLACE ( r.seqname, 'SEQ_', '' ) 
      AND constraint_name = REPLACE( REPLACE(r.seqname, '_ID', '' ), 'SEQ_', 'PK_' );
      /*
      ** Query the table to get the current maximum value - could use stats
      */
      cmd := 'SELECT MAX(' || colname || ') FROM ' || tabname;
      EXECUTE IMMEDIATE cmd INTO maxval;
      /*
      ** Set sequence to inc by that amount
      */
      cmd := 'alter sequence ' || r.seqname || ' INCREMENT BY ' || maxval;
      EXECUTE IMMEDIATE cmd;
      /*
      ** SELECT the sequence to bump its value up
      */
      cmd := 'SELECT ' || r.seqname || '.nextval FROM DUAL';
      EXECUTE IMMEDIATE cmd INTO maxval;
      /*
      ** Set sequence inc by back down
      */
      cmd := 'alter sequence ' || r.seqname || ' INCREMENT BY 1';
      EXECUTE IMMEDIATE cmd;
   END LOOP;
END;
/
但是,如果您没有可用命名约定的便利性,则可以执行以下操作:

创建一个接受序列名、表名、, 列名作为参数。 该过程将查询给定表/列的最大值 然后,该程序将通过上述调整进行增量 现在生成一个包装器存储过程,它将调用传入3个值的辅助过程。 最终结果应该是:

BEGIN
  reset_seq_val ( 'seq1', 'table1', 'col1');
  reset_seq_val ( 'seq2', 'table2', 'col2');
...
END;

这里的艰苦工作将是编译此列表,但一旦完成,您应该能够按需重新使用它。

可能的重复要重新回答您的问题,您在一个测试环境中,刚刚从生产中加载了新数据,并且您在测试环境中的序列现在“落后于”数据中的键值,因此,您需要增加测试环境序列,以便它们在刚刚加载的数据之上生成值。呼。按照提供的@OldProgrammer链接进行操作,因为它显示了方法,您应该能够以编程方式完成所有序列。