当前位置: 首页 > 面试题库 >

需要在Oracle中重置序列的值

卜盛
2023-03-14
问题内容

我正在与Spring和Hibernate一起使用Java开发Web应用程序。假设我有一张桌子。当我从该表中删除一些记录时,有时我需要重置主键字段的值。

假设我在一个表中有10条记录,而我删除了最后5条记录。现在,当我插入新记录时,主键字段的值应从开始,6但应从开始11

如果需要在MySql 中的6maximum +1)处启动主键值,则只需执行以下SQL语句。

alter table table_name auto_increment=1;

这将自动重置价值auto_increment,以maximum + 1该字段的值(在概念是不正确的,但它的工作原理)。

在Oracle(10g)中,我使用sequence主键。从数据库中删除某些记录后,Oracle中是否有一种方法可以将sequenceto的maximum + 1值重置为value ?


问题答案:

如果使用该值,则不应重置该值的原因:

如果您有20条记录并删除5-10条记录会怎样?中间有一个缝隙,无法重新设置序列。序列 永远不会
生成无间隙的数字序列
,即完美的
1、2 .. n

如果您调用.nextval并且不使用该值,那么它就 消失了 。您要删除并重新创建序列吗?如果开始插入并取消插入,Oracle
将回滚所做的操作,这些值将
消失 。如果设置,nocache则差距将减少,但会降低性能。这值得么?

您的缓存应该设置为您希望
在所有会话中
一次执行的插入次数,以避免任何性能问题。序列旨在提供一种非常快速,可扩展的方式来创建代理密钥,而无需任何锁等, 以免 重新生成正整数集。

归根结底,这丝毫没有关系。如果您将不间断的序列作为表的键,则您的数据而不是序列有问题。

回答问题:

要真正回答您的问题,您需要:

  1. 首先,找出表中的最大id(序列)值。
  2. 然后放下并重新创建序列。

找到最大值意味着您需要动态地重新创建序列,而又要牺牲性能。

如果您尝试在此期间向表中插入某些内容,它将失败,并且可能会使使用该序列的任何触发器或其他对象无效:

declare

   l_max_value number;

begin

   select max(id)
     into l_max_value
     from my_table;

   execute immediate 'drop sequence my_sequence_name';

   -- nocache is not recommended if you are inserting more than
   -- one row at a time, or inserting with any speed at all.
   execute immediate 'create sequence my_sequence_name
                           start with ' || l_max_value
                      || ' increment by 1
                           nomaxvalue
                           nocycle
                           nocache';

end;
/

正如我所说,不建议这样做,您应该忽略任何差距。

更新-又名更好的答案感谢[Jeffrey Kemp](https://stackoverflow.com/users/103295/jeffrey-

kemp):

正如杰弗里·肯普(Jeffrey Kemp)在评论中所建议的那样,有一种与文档建议相反的方法,该方法 无需 删除并重新创建序列即可。

即,通过:

  1. 计算id表中的最大值与序列的当前值之间的差。
  2. 更改顺序以此负数递增
  3. 更改顺序以再次增加1。

这样做的好处是对象仍然存在,并且触发器,授权等也得以维护。不利的一面是,如果另一个会话与您的会话同时增加此负数,则可能会返回得太远。

这是一个示范:

设置测试:

SQL> create sequence test_seq
  2   start with 1
  3   increment by 1
  4   nomaxvalue
  5   nocycle
  6   nocache;

Sequence created.

SQL>
SQL> create table tmp_test ( id number(16) );

Table created.

SQL>
SQL> declare
  2     l_nextval number;
  3  begin
  4
  5    for i in 1 .. 20 loop
  6       insert into tmp_test values ( test_seq.nextval );
  7    end loop;
  8
  9  end;
 10  /

PL/SQL procedure successfully completed.

SQL>
SQL> select test_seq.currval from dual;

   CURRVAL
----------
        20

SQL>
SQL> delete from tmp_test where id > 15;

5 rows deleted.

SQL> commit;

Commit complete.

还原顺序

SQL>
SQL> declare
  2
  3     l_max_id number;
  4     l_max_seq number;
  5
  6  begin
  7
  8     -- Get the maximum ID
  9     select max(id) into l_max_id
 10       from tmp_test;
 11
 12     -- Get the current sequence value;
 13     select test_seq.currval into l_max_seq
 14       from dual;
 15
 16     -- Alter the sequence to increment by the difference ( -5 in this case )
.
 17     execute immediate 'alter sequence test_seq
 18                          increment by ' || ( l_max_id - l_max_seq );
 19
 20     -- 'increment' by -5
 21     select test_seq.nextval into l_max_seq
 22       from dual;
 23
 24     -- Change the sequence back to normal
 25     execute immediate 'alter sequence test_seq
 26                          increment by 1';
 27
 28  end;
 29  /

PL/SQL procedure successfully completed.

SQL>
SQL> select test_seq.currval from dual;

   CURRVAL
----------
        15

SQL>


 类似资料:
  • 问题内容: 在PostgreSQL中,我可以做这样的事情: 是否有Oracle等效产品? 问题答案: 这是一个很好的过程,可以将Oracle专家Tom Kyte的任何序列重置为0 。在下面的链接中也对正反两方面进行了精彩的讨论。

  • 需求:创建一个多租户应用程序,该应用程序应该根据请求中的租户id将每个租户的数据插入到各自的PDB中。换句话说,每个租户或客户在CDB中都有自己的PDB,所有PDB都有相同的模式,然后根据请求中的租户Id选择一个数据源,并将数据插入到该PDB中。 Stack-Spring boot 2.3.0.发行版,Oracle 18c,连接池-Oracle共享通用连接池 UCP连接: Spring数据源配置类

  • 问题内容: 就像在问题中一样,如何在Oracle 10g中每年自动将Oracle序列的值重置为0? 我正在使用序列生成格式的标识符,并且每年必须将序列值重置为0。 是从Java获得的,并与Oracle的序列值连接在一起。由于外部第三方的要求,无法更改标识符的格式。感谢您的任何帮助。 问题答案: 序列并不是真正要重置的设计。但是在某些情况下,需要重置序列,例如,在设置测试数据或将生产数据合并回测试环

  • 我使用Spring boot2与Spring data jpa、hibernate和posgres一起使用。我需要一年中每1天重置一个序列,因为我们使用当前”序列id。 有没有办法用jpa重置序列?

  • 我确实在PostgreSQL中创建了一个表,带有列id序列主键。查看pgAdmin中列的属性,我可以看到: 数据类型:整数 默认:nextval(items_id_seq::regclass) (因此,如果我没有弄错的话,我确实是用“serial”关键字创建的。) 现在在我的后端代码中,我使用的方法是:jpaRepository。deleteAllInBatch(),它将“截断”我的整个表。 在这

  • 这是我的主班 这是我的控制器类 这是我的fxml文件 我怎么才能修好它?我从这里尝试一切JavaFX“位置是必需的”即使它在同一个包中 更新: