如何触发检测行是否被删除?

时间:2014-08-11 22:06:09

标签: sql oracle

我做了以下触发器:

create or replace trigger TSM_ENTITY_TRG
before insert on TSM_ENTITY
for each row
begin
select TSM_ENTITY_ID_SEQ.nextval
into :new.ID
from dual;
end;
/

代码中的序列是

CREATE SEQUENCE TSM_ENTITY_ID_SEQ
MINVALUE 12
START WITH 12
INCREMENT BY 1;

触发器按需要工作,除了一件事,如果我删除一行,则触发器继续向行添加增量。例如,行的id将是12然后下一个将是13然后是14然后是15.然后,假设我删除了第15行并在之后添加了新行。然后行ID将被列为12然后是13然后是14然后是16.有没有办法让序列或触发器检测到间隙并填充它?

2 个答案:

答案 0 :(得分:0)

没有。由序列填充的列将具有间隙。如果您的要求是无间隙值,则不能使用序列。

如果你真的,真的认为你需要一个无间隙的值集,那么你必须引入一个序列化机制,确保一次只有一个用户将数据插入表中。这是可能的。但它从根本上降低了应用程序的可伸缩性和性能。并且它会大大增加您在遇到维护问题的可能性,例如在持有DBA必须找到并在任何人继续工作之前杀死的锁定而死亡的会话。我从未遇到过这样一种情况:商业用户在听到产生无差距价值的缺点后,决定他们真的想要承担这些费用。

如果您只想查看查询中的无间隙值集,可以使用rank等分析函数

SELECT rank() over (order by id) gap_free_rank
  FROM tsm_entity;

答案 1 :(得分:0)

这是一个坏主意,您必须忽略主键的值。这个值只需要检测值指向的行。

作为您的任务的解决方案:

我们假设我们有这种表结构:

create table TSM_ENTITY (
  id NUMBER(10),
  code VARCHAR2(20 char),
  name VARCHAR2(20 char)  
);

然后您可以根据表格创建视图:

CREATE VIEW TSM_ENTITY_V AS
SELECT ROW_NUMBER() over(order by id) AS id, t.code, t.name
  FROM TSM_ENTITY t

ROW_NUMBER()函数为您提供连续的数字范围。