[原創]oracle 順序號生成函數。仿Sequence


問題提出自項目中的老代碼:一個Bill表,存儲所有的表單信息,比如:員工入職單,離職單等等。(別噴,我知道要分多個表。但領導的意願你是沒辦法違背的)表單的單據號是以四個字母+年月日+數字順序號來表示。每次取新單據號時要從Bill表里(按生成規則)查詢出最大的那個單據號,再拆分出來,再給順序號加1,組合好后再寫回。哈哈這就是老代碼。

隨着軟件行業的進步,各種技巧層出不窮。而針對順序號生成的方法也有好巨大改進。

[Oracle]仿Oracle Sequence的自定義年份Sequence(適合任何數據庫)

這里其中的一篇。看過這個之后就想自己動手也寫一個。於是:

順序號表

 1 --id序列表
 2 create table SEQUENCES
 3 (
 4   id           VARCHAR2(20) not NULL PRIMARY KEY,--標識
 5   minvalue     NUMBER default 1,--最小值
 6   maxvalue     NUMBER default 9999999999999999999999999999,--最大值
 7   currentvalue NUMBER DEFAULT 1,--當前值
 8   increaseby   NUMBER default 1,--增量
 9   CYCLE        CHAR(1) default '0' --是否循環
10 )

生成函數

 1 --獲取 select NextValue('abc') from dual;
 2 create or replace function NextValue(arg varchar2) return number IS
 3   PRAGMA AUTONOMOUS_TRANSACTION;
 4   Result number;
 5   x NUMBER;
 6   a NUMBER;
 7   i NUMBER;
 8   c Char(1);
 9 BEGIN
10   IF TRIM(arg) IS NULL THEN--防止值入空字符串
11      RAISE_Application_Error(-6502,'param "arg" is not valide.',TRUE);
12   END IF;
13 <<top>>
14   SELECT COUNT(1) INTO x FROM Sequences WHERE ID = arg;
15    IF x = 0 THEN
16    BEGIN
17       BEGIN
18         INSERT INTO Sequences (ID) VALUES(arg);--防止並發同時插入相同的Id值。需要將id設為主鍵
19       EXCEPTION
20         WHEN OTHERS THEN
21           GOTO top;
22       END;
23       COMMIT;
24       RETURN 1;
25    END;
26    ELSE
27    BEGIN
28      SELECT s.currentvalue + s.increaseby,s.maxvalue,s.minvalue,s.cycle INTO Result,a,i,c FROM  Sequences s WHERE ID = arg FOR update;--for update將鎖定此行記錄
29      IF RESULT < a THEN--未超出最大值
30      BEGIN
31        UPDATE Sequences SET currentvalue = Result WHERE ID = arg;
32        COMMIT;
33        return(Result);
34      END;
35      ELSE
36      BEGIN
37        IF c = '0' THEN--不循環
38        BEGIN
39           RAISE_Application_Error(-6502,'out of range.',TRUE);
40        END;
41        ELSE
42        BEGIN--循環
43           UPDATE Sequences SET currentvalue = i WHERE ID = arg;
44           COMMIT;
45           RETURN i;
46        END;
47        END IF;
48      END;
49      END IF;
50    END;
51    END IF;
52 END;

是的,我使用了參數。這樣就使得這個表更加有用,而非只單獨處理一種類型順序號。同時對並發進行了處理。讓你只可能取得一個值,而不會出現重復的值。當然所有的result都沒有進行格式化,而是直接輸出。在PLSQL中進行函數test,打開兩個窗口,單步調試,可以看到在insert或select for update時都會阻塞其它session對此表的操作。這樣可以使用result的結果唯一。

如果將表的名稱的傳入,那么你可以扔掉sequence了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM