zoukankan      html  css  js  c++  java
  • [原创]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了。

  • 相关阅读:
    原型和原型链的理解
    vue2.0 购物车小球的实现
    canvas 实现规则多边形
    ES6全套教程
    利用canvas实现雪花的飘动
    前端 原型对象中this的认识
    JavaScript——创建对象
    javaScript——原型继承四步曲
    AltiumDesigner使用小窍门 (转)
    C指针理解(转)
  • 原文地址:https://www.cnblogs.com/goldli/p/MockSequence.html
Copyright © 2011-2022 走看看