Oracle 9 - 重置序列以匹配表的状态

AJM*_*AJM 18 oracle sequence oracle9i

我有一个序列用于在oracle表中播种我的(基于Integer的)主键.

看来这个序列并不总是用于在表中插入新值.如何将序列与表中的实际值一起返回?

dpb*_*ley 16

如果ID是PK列的名称,PK_SEQ是序列的名称:

  1. 通过SELECT MAX(ID)FROM tableName查找最高PK的值

  2. 通过SELECT PK_SEQ.NEXTVAL FROM DUAL查找下一个PK_SEQ的值

  3. 如果#2>#1则不需要做任何事情,假设您将这些值视为真正的代理键
  4. 否则,通过ALTER SEQUENCE PK_SEQ INCREMENT BY [#1 value - #2 value]更改序列以跳转到最大ID
  5. 通过SELECT PK_SEQ.NEXTVAL FROM DUAL压缩序列

  6. 通过ALTER SEQUENCE PK_SEQ INCREMENT BY 1将序列增量值重置为1

这一切都假设您在执行此操作时没有新的插入表...

  • 步骤3的目的是将最大PK值与下一个序列值进行比较.因此,例如,如果步骤1中的SELECT导致结果为100,则步骤2中的SELECT导致结果为90表示您已"跳转"了11个序列.当您在步骤4中更改序列时,步骤5中的SELECT将序列10值移动到100.在步骤6中重置增量后,下一个"SELECT PK_SEQ.NEXTVAL FROM DUAL"将为您提供101. (2认同)

Dav*_*res 11

总之,游戏吧:

-- Current sequence value is 1000

ALTER SEQUENCE x INCREMENT BY -999;
Sequence altered.

SELECT X.NEXTVAL FROM DUAL;
1

ALTER SEQUENCE x INCREMENT BY 1;
Sequence altered.
Run Code Online (Sandbox Code Playgroud)

您可以获取表中使用的最大序列值,进行数学运算并相应地更新序列.


Die*_*ker 8

Declare
  difference INTEGER;
  sqlstmt varchar2(255);
  sequenceValue Number;
begin
sqlstmt := 'ALTER SEQUENCE YOURSEQUENCE INCREMENT BY ';
select YOURSEQUENCE.NEXTVAL into sequenceValue from dual;
select  (nvl(Max(YOURID),0) - sequenceValue)+1 into difference from YOURTABLE;
if difference > 0 then
  EXECUTE IMMEDIATE sqlstmt || difference;
  select  YOURSEQUENCE.NEXTVAL INTO sequenceValue from dual;
  EXECUTE IMMEDIATE sqlstmt || 1;
end if;
end;
Run Code Online (Sandbox Code Playgroud)


Bla*_*ama 5

我制作了这个脚本,因为我没有找到一个在线脚本,它动态地将我的所有序列设置为当前最高ID.在Oracle 11.2.0.4上测试.

DECLARE
  difference         INTEGER;
  sqlstmt            VARCHAR2(255) ;
  sqlstmt2           VARCHAR2(255) ;
  sqlstmt3           VARCHAR2(255) ;
  sequenceValue      NUMBER;
  sequencename       VARCHAR2(30) ;
  sequencelastnumber INTEGER;
  CURSOR allseq
  IS
     SELECT sequence_name, last_number FROM user_sequences ORDER BY sequence_name;
BEGIN
  DBMS_OUTPUT.enable(32000) ;
  OPEN allseq;
  LOOP
    FETCH allseq INTO sequencename, sequencelastnumber;
    EXIT
  WHEN allseq%NOTFOUND;
    sqlstmt  := 'ALTER SEQUENCE ' || sequencename || ' INCREMENT BY ';
    --Assuming: <tablename>_id is <sequencename>
    sqlstmt2 := 'select (nvl(Max(ID),0) - :1)+1 from ' || SUBSTR(sequencename, 1, LENGTH(sequencename) - 3) ;
    --DBMS_OUTPUT.PUT_LINE(sqlstmt2);
    --Attention: makes use of user_sequences.last_number --> possible cache problems!
    EXECUTE IMMEDIATE sqlstmt2 INTO difference USING sequencelastnumber;
    IF difference > 0 THEN
      DBMS_OUTPUT.PUT_LINE('EXECUTE IMMEDIATE ' || sqlstmt || difference) ;
      EXECUTE IMMEDIATE sqlstmt || difference;
      sqlstmt3 := 'SELECT ' || sequencename ||'.NEXTVAL from dual';
      DBMS_OUTPUT.PUT_LINE('EXECUTE IMMEDIATE ' || sqlstmt3 || ' INTO sequenceValue') ;
      EXECUTE IMMEDIATE sqlstmt3 INTO sequenceValue;
      DBMS_OUTPUT.PUT_LINE('EXECUTE IMMEDIATE ' || sqlstmt || 1) ;
      EXECUTE IMMEDIATE sqlstmt || 1;
      DBMS_OUTPUT.PUT_LINE('') ;
    END IF;
  END LOOP;
  CLOSE allseq;
END;
Run Code Online (Sandbox Code Playgroud)