Oracle 在表中添加和删除时使用序列

Oracle 在表中添加和删除时使用序列,oracle,plsql,triggers,sequence,Oracle,Plsql,Triggers,Sequence,我正在创建一个表,在其中添加文件名和许多其他字段。我使用fileid列按顺序表示文件;i、 e.要上传的第一个文件应该具有fieldid 1,然后下一个文件将具有fileid 2,依此类推。我使用了序列和触发器: create sequence create_file_id start with 1 increment by 1 nocache; 触发因素是: before insert on add_files_details for each row begin select create

我正在创建一个表,在其中添加文件名和许多其他字段。我使用fileid列按顺序表示文件;i、 e.要上传的第一个文件应该具有fieldid 1,然后下一个文件将具有fileid 2,依此类推。我使用了序列和触发器:

create sequence create_file_id start with 1 increment by 1 nocache;
触发因素是:

before insert on add_files_details
for each row
begin
select create_file_id.nextval into :new.file_id from dual;
end;
但是,如果从表中删除了任何记录,那么序列就会变得混乱。因此,我考虑使用另一个带有触发器的序列,将前一个序列的值减去删除的行数。但我被困在执行这个序列的触发器

顺序:

create sequence del_file_id increment by -1 nocache;

有没有办法做到这一点?

您可以让序列执行主键工作,并创建基表的视图,选择

rownum作为要按顺序查看从1到N的数字的列:

SQL> create table your_table(
  2    tab_id number primary key,
  3    col    number
  4  )
  5  ;

Table created

SQL> create sequence gen_id;

Sequence created

SQL> create trigger TR_PK_your_table
  2  before insert on your_table
  3  for each row
  4  begin
  5    :new.tab_id := gen_id.nextval; -- This kind of assignment is allowed in 11g  
  6  end;                             -- and higher, in version prior to 11g 
  7  /                                -- conventional select statement is used

Trigger created

SQL> insert into your_table(col)
  2  select level 
  3    from dual
  4  connect by level <=7;

7 rows inserted

SQL> commit;

Commit complete

SQL> select *
  2    from your_table;

    TAB_ID        COL
---------- ----------
         1          1
         2          2
         3          3
         4          4
         5          5
         6          6
         7          7

7 rows selected

SQL> create or replace view V_your_table
  2  as
  3  select tab_id
  4       , col
  5       , rownum as num
  6    from your_table
  7  ;

View created

SQL> select *
  2    from v_your_table;

    TAB_ID        COL        NUM
---------- ---------- ----------
         1          1          1
         2          2          2
         3          3          3
         4          4          4
         5          5          5
         6          6          6
         7          7          7

7 rows selected

SQL> delete from your_table where tab_id in (3,5,6);

3 rows deleted

SQL> commit;

Commit complete

SQL> select *
  2    from your_table;

    TAB_ID        COL
---------- ----------
         1          1
         2          2
         4          4
         7          7

SQL> select *
  2    from v_your_table;

    TAB_ID        COL        NUM
---------- ---------- ----------
         1          1          1
         2          2          2
         4          4          3
         7          7          4

SQL> 
阅读为什么你不想尝试创建一个无间隙序列

@尼古拉斯在那里有一个很好的方法,以前从未想过

然而,有几个问题

如果在视图中使用rownum,还必须在TAB_ID上包含orderby语句。 使用示例中的TAB_ID;在RAC系统中,无法保证您将获得下一个可用号码,因此“订购方式”可能没有帮助。 不过,可以稍微扩展一下该方法,在表中添加一个日期或时间戳列,然后在ORDERBY中使用该列。我还没有测试过这种方法

回到AskTom的观点,你想要一个无间隙序列的具体原因是什么

当盒子所在房间上方的水管爆裂,50个盒子完全损坏时会发生什么 无法使用

或者有人无意中打碎了一个盒子

或者——不管怎样

它一般不是无间隙的。这不是一个系统分配的,gap 自由顺序或者


也许有一些方法可以做到这一点,但充其量它将是一种复杂的方式来完成一些价值值得怀疑的事情,最坏的情况下,它将是有缺陷的、缓慢的和不可靠的。去了那里,做了那件事,后悔了。我强烈建议你重新考虑。这是一个非常棘手但简单的解决方案。感谢您指出这个解决方案我们正在开发一个文档共享站点,前端是Java,后端是oracle pl/sql。因此,当我们想要添加文件时,应该按顺序生成id。但若文件从此表中删除,则必须从此表中删除整行,并将其插入另一个名为“已删除文件详细信息”的表中。最后,我们必须生成一份关于添加和删除文件的完整报告。这就是为什么,我们需要一个序列。此外,我们正在考虑根据文件类型而不是长文件名引用和排序文件id,这将加快搜索过程。我使用了序列,这是一种完全可以接受的使用序列的方式。在我看来,问题是试图保持某种无间隙的顺序。那是不必要的。出于上述原因,请小心接受答案的方法。祝你好运