Triggers 使用序列和触发器,我在Oracle10g中自动递增了我的表,但ID是无序的

Triggers 使用序列和触发器,我在Oracle10g中自动递增了我的表,但ID是无序的,triggers,oracle10g,sequence,auto-increment,Triggers,Oracle10g,Sequence,Auto Increment,我在表测试中输入了2行,并以自动递增的形式获得ID,但是当我输入第三条记录时,ID变成了8。 删除该记录并输入新的第三条记录时,ID为9 我如何解决这个问题?我希望所有的ID都是连续的,即使在我删除记录或进行更改之后也是如此 Oracle序列永远不能保证生成无间隙的值集。您可以通过消除序列缓存(这会对性能产生负面影响)之类的操作来最小化间隙,但无法消除它们。您是否真的确定存在差距会给您带来问题?在我所见过的每一个案例中,当有人认为他们想要一套无差距的价值观时,正确的答案是接受这些差距,而不是处理

我在表测试中输入了2行,并以自动递增的形式获得ID,但是当我输入第三条记录时,ID变成了8。 删除该记录并输入新的第三条记录时,ID为9


我如何解决这个问题?我希望所有的ID都是连续的,即使在我删除记录或进行更改之后也是如此

Oracle序列永远不能保证生成无间隙的值集。您可以通过消除序列缓存(这会对性能产生负面影响)之类的操作来最小化间隙,但无法消除它们。您是否真的确定存在差距会给您带来问题?在我所见过的每一个案例中,当有人认为他们想要一套无差距的价值观时,正确的答案是接受这些差距,而不是处理生成无差距序列的权衡问题

如果确实需要无间隙序列,则需要强制对表的所有更改进行序列化,以便一次只能有一个会话插入或删除行。这大大降低了应用程序的可伸缩性,并可能导致各种维护问题,例如,当用户外出吃饭时,一个会话持有锁,或者当客户端应用程序崩溃,迫使其他所有人停止工作,直到DBA发现并杀死有问题的会话。这比简单地生活在主键价值观的差距中要糟糕得多

如果您真的想沿着这条路走下去,您可能需要创建一个新表

CREATE TABLE my_slow_sequence( 
  table_name varchar2(30) primary key,
  val        number
);

INSERT INTO my_slow_sequence( 'TABLE_NAME', 1 );
在插入之前触发的行级触发器中(如果希望修改密钥,则更新),需要锁定有问题的行(确保访问被序列化)

选择val
进入:新的。
从我的慢序列
其中table_name='table_name'
更新;
更新我的\u慢\u序列
设置val=val+1
其中table_name='table_name'
在删除后触发的语句级触发器中,您需要执行相同的过程来锁定
my\u slow\u序列中的行。然后,您需要扫描该表以确定要设置的
val
,或者需要一个行级别的before delete触发器,该触发器在一个单独的包中定义的集合中捕获已删除的
值,您可以在语句级别触发器中进行迭代

如果您希望允许更新键值,那么在更新时需要一个或多个触发器,类似于您需要处理删除的触发器

试图用触发器处理这一问题将涉及大量代码和许多移动的片段,并将破坏系统的性能。这真的不值得。学会接受主键会有间隙

SELECT val
  INTO :new.<<pk_column>>
  FROM my_slow_sequence
 WHERE table_name = 'TABLE_NAME'
   FOR UPDATE;

UPDATE my_slow_sequence
   SET val = val + 1
 WHERE table_name = 'TABLE_NAME'