【问题标题】:How to handle auto increment sequence on dup_val_on_index oracle sql如何处理 dup_val_on_index oracle sql 上的自动递增序列
【发布时间】:2020-01-17 05:12:02
【问题描述】:

我有一个 oracle 表

  1. 使用序列的自动递增主键。
  2. 唯一键
  3. 非唯一字段
create table FOO (
    ai_id number primary key,
    name varchar(20),
    bar varchar(20)
    CONSTRAINT foo_uk_name UNIQUE (name)
);
create sequence  FOO_seq;

create or replace trigger FOO_trg
before insert on FOO
for each row
begin
  select FOO_seq.nextval into :new.ai_id from dual;
end;

我有单独的存储过程来更新表格

create PROCEDURE UPSERT_FOO(
  name_input IN VARCHAR2,
  bar_input IN VARCHAR2
begin
  begin
    insert into FOO ( name, bar )
    values ( name_input, bar_input )
  exception
    when dup_val_on_index then
      update FOO 
      set  bar = bar_input
      where name = name_input
  end;
end;

这工作得很好,但唯一的问题是,序列“FOO_seq”总是增加,无论它是更新还是插入(因为 FOO_seq 在插入之前在“FOO_trg”中增加)。

有没有办法在不影响性能的情况下,只在插入时增加序列?

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

    Oracle 有一个内置的merge statement 来执行“更新插入”:

    create PROCEDURE UPSERT_FOO(
      name_input IN VARCHAR2,
      bar_input IN VARCHAR2
    ) as
    begin
      merge into foo
      using (
        select name_input as name, bar_input as bar from dual
      ) src
      on (foo.name = src.name)
      when matched then
        update set foo.bar = src.bar
      when not matched then
        insert (name, bar)
        values (src.name, src.bar);
    end;
    /
    

    只有在没有匹配的情况下才会发生插入(因此触发器只会触发,增加序列)。

    当然,现在不必通过程序来完成;您可以直接发出合并,插入您当前必须传递给过程的名称/栏值。

    顺便说一句,您的触发器可以稍微简化以执行分配:

    create or replace trigger FOO_trg
    before insert on FOO
    for each row
    begin
      :new.ai_id := FOO_seq.nextval;
    end;
    /
    

    dbfiddles 使用your original code 和使用the code above。注意最终查询中“b”的 ID;第一个有 5 个,第二个只有 2 个。

    当然,序列中的间隙应该无关紧要;它们保证递增并且是唯一的(如果它们不循环),不是是无缝的。或者,如果您有缓存并且正在使用 RAC,则必须以严格的顺序发布。不过,您的方法可能会无缘无故地浪费大量价值,而且不需要那么复杂。

    【讨论】:

    • 感谢 Alex 的详细解释。
    猜你喜欢
    • 2016-06-24
    • 1970-01-01
    • 2014-04-15
    • 2013-12-01
    • 2014-09-09
    • 2011-11-21
    • 2020-01-15
    • 2015-11-03
    • 1970-01-01
    相关资源
    最近更新 更多