簡體   English   中英

發生異常時遞減 oracle 序列

[英]Decrement oracle sequence when an exception occurred

我嘗試使用 pl/sql 在我的數據庫中插入一條新記錄,所以首先我生成一個新序列,如下所示:

select my_seq.nextval into seqId from dual;

然后我嘗試使用生成的 seqId 插入一條新記錄,如下所示:

insert into myTable (id) values seqId ;

但是當插入過程中發生錯誤時,我想在異常塊中減少我的序列。 請問有人有想法嗎?

您不能在序列遞增后遞減(一個序列要么遞增要么遞減,而不是兩者)或重新初始化 Oracle 中的序列(從...開始)。 沒有辦法做到這一點。 希望這可以幫助。

但是,如果你想繼續這種荒謬的做法,你可以試試這個,但你需要先初始化你的序列,即 myseq.nextval; 那么您可以首先嘗試插入 currval ,如果成功,那么您可以增加您的序列,否則序列將具有其先前的值。

Declare 
currval pls_integer;
inc pls_integer;
Begin

select seq.currval into currval from dual;

insert into myTable (id) values (currval) ;
select seq.nextval into inc from dual;

Exception
when others then
do the exception handling;
end;

正如你已經被告知的那樣,你根本不應該這樣做。 無論如何,這就是你可以做到的方式。

示例表和序列:

SQL> create table mytable (id number primary key);

Table created.

SQL> create sequence seq;

Sequence created.

SQL> set serveroutput on

seq.nextval插入mytable並在發生故障時遞減序列的過程。 我正在以最簡單的方式進行操作 - 將其刪除並重新創建,並將start參數設置為最后獲取的值 - 1 DBMS_OUTPUT調用在這里只是為了顯示過程中發生了什么。

SQL> create or replace procedure p_test as
  2    seqid number;
  3  begin
  4    seqid := seq.nextval;
  5    dbms_output.put_line('Sequence number to be inserted = ' || seqid);
  6
  7    insert into mytable(id) values (seqid);
  8
  9  exception
 10    when others then
 11      dbms_output.put_line(sqlerrm);
 12      execute immediate 'drop sequence seq';
 13      execute immediate 'create sequence seq start with ' || to_char(seqid - 1);
 14  end;
 15  /

Procedure created.

讓我們測試一下:這應該插入1

SQL> exec p_test;
Sequence number to be inserted = 1

PL/SQL procedure successfully completed.

SQL> select * from mytable;

        ID
----------
         1

到目前為止,一切都很好。 現在,我將手動插入ID = 2 ,以便下一個過程調用違反唯一約束:

SQL> insert into mytable values (2);

1 row created.

再次調用該過程:

SQL> exec p_test;
Sequence number to be inserted = 2
ORA-00001: unique constraint (SCOTT.SYS_C007547) violated

PL/SQL procedure successfully completed.

好的; 程序默默地完成。 它沒有插入任何東西,但它減少了序列:

SQL> select * from mytable;

        ID
----------
         1        --> populated with the first P_TEST call
         2        --> populated manually

SQL> select seq.nextval from dual;

   NEXTVAL
----------
         1        --> sequence is decremented from 2 to 1

如果我刪除有問題的ID = 2並重試:

SQL> delete from mytable where id = 2;

1 row deleted.

SQL> exec p_test;
Sequence number to be inserted = 2

PL/SQL procedure successfully completed.

SQL> select * from mytable;

        ID
----------
         1
         2

SQL> select seq.nextval from dual;

   NEXTVAL
----------
         3

SQL>

正確的; 作品,但它不值得痛苦。

此外,正如您所說,一個表中有 20 行。 如果有人刪除了第 13 行,你會怎么做。 你會遞減 #14 到 20 之間的所有值嗎? 如果那是一些外鍵引用的主鍵怎么辦?

說真的,不要這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM