[原创]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了。

 

转载于:https://www.cnblogs.com/goldli/p/MockSequence.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值