在使用时不应重置该值的原因:
如果您有 20 条记录并删除 5-10 条记录会怎样?您中间有一个间隙,重新设置序列将无法解决。序列将never generate a gap free sequence of numbers,一个完美的1, 2 .. n。
如果您调用.nextval 并且不使用该值,它已消失。您要删除并重新创建序列吗?如果您开始插入并取消它,Oracle rolls back 您所做的这些值将消失。如果您设置nocache,那么您的差距会更小,但会影响性能;这值得么?
您的缓存应设置为您希望在任何时候执行的插入次数across all sessions 以避免任何性能问题。序列旨在提供一种非常快速、可扩展的方式来创建没有任何锁等不的代理键来重新生成正整数集。
归根结底,这应该无关紧要。如果您依赖完整的序列作为表的键,那么您的数据而不是序列有问题。
回答问题:
要真正回答您的问题,您需要:
- 首先,找出表中的最大 id(序列)值是多少。
- 然后drop and re-create the sequence。
找到最大值意味着您需要以再次影响性能为代价动态地重新创建序列。
如果您在发生这种情况时尝试向表中插入某些内容,它将失败,并且可能会使使用该序列的任何触发器或其他对象无效:
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 在 cmets 中所建议的那样,有一种方法可以做到这一点删除并重新创建序列。
即,由:
- 计算表中最大
id 与序列当前值之间的差异。
- 改变序列以增加这个负数
- 更改序列以再次增加 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>