如何使用循环更改 Oracle 序列?

发布于 2024-11-03 20:06:16 字数 226 浏览 1 评论 0原文

希望有人能帮忙。当我尝试将某些内容插入表中时,出现错误,提示主键已存在。所以我需要重置我的序列,使其始终为 max(id)+1。

该表称为“人员”,有 2 列(ID、姓名)。该序列称为SEQ。

我正在考虑做一个循环。要从 Dual 中选择 SEQ.nextval 运行 n 次。这个 n= max(id)-SEQ.currval

这行得通吗?以及如何将其放入语法中?

多谢。

Hope someone can help. When I tried to insert something into a table it give me error saying the primary key is already existed. So I need to reset my sequence so that it is always max(id)+1.

The table is called 'People' with 2 columns (ID, Name). The sequence is called SEQ.

I am thinking of doing a loop. To run select SEQ.nextval from dual for n times. this n= max(id)-SEQ.currval

Wwill this work? and how Can I put it into the syntax?

Thanks a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧伤还要旧人安 2024-11-10 20:06:16
declare
  l_MaxVal  pls_integer;
  l_Currval pls_integer default - 1;
begin
  select max(id)
    into l_MaxVal
    from people;
  while l_Currval < l_Maxval
  loop
    select my_seq.nextval
      into l_Currval
      from dual;
  end loop;
end;
declare
  l_MaxVal  pls_integer;
  l_Currval pls_integer default - 1;
begin
  select max(id)
    into l_MaxVal
    from people;
  while l_Currval < l_Maxval
  loop
    select my_seq.nextval
      into l_Currval
      from dual;
  end loop;
end;
月亮坠入山谷 2024-11-10 20:06:16

如果这是一次性的,您可以使用更改序列
改变序列sequenceName增量val;
而 val 为最大值+1
然后调用 get nextVal,然后将增量设置回 1。

我将下面的内容放在一起,向您展示如何在不循环的情况下完成它。

create sequence changeValue start with 18 increment by 1 nocache ;
select changeValue.nextval from dual ;
/

NEXTVAL                
---------------------- 
18  



set serveroutput on
declare
 maxVal     number := 24 ;
 curVal     number ;
 diffVal      number ;
 incrementVal number ;


 procedure alterSequence(seqName in varchar2, incVal in number) as
    s varchar2(500);
    begin
       s := 'alter sequence ' || seqName || ' increment by  ' || incVal ;
       dbms_output.put_line(s);
       execute immediate s;
    end alterSequence;
begin
    --(done in 11gr2 so if in earlier version select into)
     curVal := changeValue.currval ;
    dbms_output.put_line('curValue=>' || curVal );
    diffVal :=  maxVal - curVal ;
    dbms_output.put_line('diffVal=>' || diffVal );

    alterSequence ( 'changeValue' , diffVal + 1 );
    incrementVal   := changeValue.nextval ;
    dbms_output.put_line('incrementVal=>' || incrementVal );
    alterSequence ( 'changeValue' , 1 );
    curVal := changeValue.currval ;
    dbms_output.put_line('curValue=>' || curVal ); 
end ;
/


curValue=>18
diffVal=>6
alter sequence changeValue increment by  7
incrementVal=>25
alter sequence changeValue increment by  1
curValue=>25

或者更好的是,正如 @Dave 建议的那样,只需删除并使用可接受的 开始 值重新创建序列即可。

If this is a one off, you can use the alter sequence
alter sequence sequenceName increment by val ;
whereas val is +1 to the maximum
then call get nextVal, then set the increment back to 1.

I threw the below together to show you how it can be done without looping.

create sequence changeValue start with 18 increment by 1 nocache ;
select changeValue.nextval from dual ;
/

NEXTVAL                
---------------------- 
18  



set serveroutput on
declare
 maxVal     number := 24 ;
 curVal     number ;
 diffVal      number ;
 incrementVal number ;


 procedure alterSequence(seqName in varchar2, incVal in number) as
    s varchar2(500);
    begin
       s := 'alter sequence ' || seqName || ' increment by  ' || incVal ;
       dbms_output.put_line(s);
       execute immediate s;
    end alterSequence;
begin
    --(done in 11gr2 so if in earlier version select into)
     curVal := changeValue.currval ;
    dbms_output.put_line('curValue=>' || curVal );
    diffVal :=  maxVal - curVal ;
    dbms_output.put_line('diffVal=>' || diffVal );

    alterSequence ( 'changeValue' , diffVal + 1 );
    incrementVal   := changeValue.nextval ;
    dbms_output.put_line('incrementVal=>' || incrementVal );
    alterSequence ( 'changeValue' , 1 );
    curVal := changeValue.currval ;
    dbms_output.put_line('curValue=>' || curVal ); 
end ;
/


curValue=>18
diffVal=>6
alter sequence changeValue increment by  7
incrementVal=>25
alter sequence changeValue increment by  1
curValue=>25

or better yet, as @Dave suggests, just drop and recreate the sequence with the acceptable Start With value.

寻找我们的幸福 2024-11-10 20:06:16

有了这个,您就可以同步序列,无论它是在 ID 最大值之前还是之后。

只需要更改代码最后的参数即可。

    declare
      procedure SYNC_SEQUENCE
        (  P_IN_SEQ          in     varchar2
         , P_IN_TABLE        in     varchar2
         , P_IN_ID           in     varchar2
        )
        is
          LV_MAXVAL          number  := 0;
          LV_CURRVAL         number  := -1;
          LV_AUX NUMBER;
        begin

          execute immediate
              'select max('||P_IN_ID||')
                 from '||P_IN_TABLE   into LV_MAXVAL;
          execute immediate 
              'select '||P_IN_SEQ||'.nextval
                from dual ' into LV_CURRVAL;             

          if LV_MAXVAL < LV_CURRVAL then
            LV_AUX := (LV_CURRVAL - LV_MAXVAL);
            execute immediate 
                 'ALTER SEQUENCE '||P_IN_SEQ||' INCREMENT BY -'||LV_AUX;
            execute immediate 
                 'SELECT '||P_IN_SEQ||'.NEXTVAL FROM dual' INTO LV_AUX;
            execute immediate 
                 'ALTER SEQUENCE '||P_IN_SEQ||' INCREMENT BY 1';
          end if;

          while LV_CURRVAL < LV_MAXVAL
          loop
             execute immediate 
                'select '||P_IN_SEQ||'.nextval
                  from dual ' into LV_CURRVAL;
          end loop;
        end SYNC_SEQUENCE;

    begin
      SYNC_SEQUENCE('MY_SEQUENCIE_NAME','MY_TABLE_NAME','MY_FIELD_ID_NAME');
    end;
    /

With this one you can synchronize the sequence whatever it is forward or behind the max of the ID.

Just need to change the parameters in the final of the code.

    declare
      procedure SYNC_SEQUENCE
        (  P_IN_SEQ          in     varchar2
         , P_IN_TABLE        in     varchar2
         , P_IN_ID           in     varchar2
        )
        is
          LV_MAXVAL          number  := 0;
          LV_CURRVAL         number  := -1;
          LV_AUX NUMBER;
        begin

          execute immediate
              'select max('||P_IN_ID||')
                 from '||P_IN_TABLE   into LV_MAXVAL;
          execute immediate 
              'select '||P_IN_SEQ||'.nextval
                from dual ' into LV_CURRVAL;             

          if LV_MAXVAL < LV_CURRVAL then
            LV_AUX := (LV_CURRVAL - LV_MAXVAL);
            execute immediate 
                 'ALTER SEQUENCE '||P_IN_SEQ||' INCREMENT BY -'||LV_AUX;
            execute immediate 
                 'SELECT '||P_IN_SEQ||'.NEXTVAL FROM dual' INTO LV_AUX;
            execute immediate 
                 'ALTER SEQUENCE '||P_IN_SEQ||' INCREMENT BY 1';
          end if;

          while LV_CURRVAL < LV_MAXVAL
          loop
             execute immediate 
                'select '||P_IN_SEQ||'.nextval
                  from dual ' into LV_CURRVAL;
          end loop;
        end SYNC_SEQUENCE;

    begin
      SYNC_SEQUENCE('MY_SEQUENCIE_NAME','MY_TABLE_NAME','MY_FIELD_ID_NAME');
    end;
    /
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文