强制获取序列下一个值/当前值(oracle函数)

推荐

作者:靓仔小伙计

作者:周公

oracle创建序列:

先假设有这么一个表:

create table S_Depart  (
   DepartId             INT                             not null,
   DepartName           NVARCHAR2(40)                   not null,
   DepartOrder          INT                            default 0,
   constraint PK_S_DEPART primary key (DepartId)
);

Oracle中sequence就是所谓的序列号,每次取的时候它会自动增加,一般用在需要按序列号排序的地方。 
1、Create Sequence 
你首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE权限, 
CREATE SEQUENCE emp_sequence 
INCREMENT BY 1 -- 每次加几个 
START WITH 1 -- 从1开始计数 
NOMAXvalue -- 不设置最大值 
NOCYCLE -- 一直累加,不循环 
CACHE 10; --设置缓存cache个序列,如果系统down掉了或者其它情况将会导致序列不连续,也可以设置为---------NOCACHE
针对S_Depart创建的sequence如下:

create sequence S_S_DEPART
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
nocache;

一旦定义了emp_sequence,你就可以用CURRVAL,NEXTVAL 
CURRVAL=返回 sequence的当前值 
NEXTVAL=增加sequence的值,然后返回 sequence 值 
比如: 
emp_sequence.CURRVAL 
emp_sequence.NEXTVAL 
可以使用sequence的地方: 
- 不包含子查询、snapshot、VIEW的 SELECT 语句 
- INSERT语句的子查询中 
- NSERT语句的valueS中 
- UPDATE 的 SET中 
可以看如下例子:

insert into S_Depart(departId,Departname,Departorder)values(S_S_Depart.Nextval,‘12345‘,1);
SELECT empseq.currval FROM DUAL; 

但是要注意的是: 
- 第一次NEXTVAL返回的是初始值;随后的NEXTVAL会自动增加你定义的INCREMENT BY值,然后返回增加后的值。CURRVAL 总是返回当前SEQUENCE的值,但是在第一次NEXTVAL初始化之后才能使用CURRVAL,否则会出错。一次NEXTVAL会增加一次 SEQUENCE的值,所以如果你在同一个语句里面使用多个NEXTVAL,其值就是不一样的。明白? 
- 如果指定CACHE值,oracle就可以预先在内存里面放置一些sequence,这样存取的快些。cache里面的取完后,oracle自动再取一组到cache。 使用cache或许会跳号, 比如数据库突然不正常down掉(shutdown abort),cache中的sequence就会丢失. 所以可以在create sequence的时候用nocache防止这种情况。 
2、Alter Sequence 
你或者是该sequence的owner,或者有ALTER ANY SEQUENCE 权限才能改动sequence. 可以alter除start至以外的所有sequence参数.如果想要改变start值,必须 drop sequence 再 re-create . 
Alter sequence 的例子

ALTER SEQUENCE emp_sequence
INCREMENT BY 10
MAXvalue 10000
CYCLE -- 到10000后从头开始
NOCACHE ; 

影响Sequence的初始化参数:

SEQUENCE_CACHE_ENTRIES =设置能同时被cache的sequence数目。 

可以很简单的Drop Sequence

DROP SEQUENCE order_seq; 

一个简单的例子:

create sequence SEQ_ID
minvalue 1
maxvalue 99999999
start with 1
increment by 1
nocache
order;

建解发器代码为:

create or replace trigger tri_test_id
  before insert on S_Depart   --S_Depart 是表名
  for each row
declare
  nextid number;
begin
  IF :new.DepartId IS NULLor :new.DepartId=0 THEN --DepartId是列名
    select SEQ_ID.nextval --SEQ_ID正是刚才创建的
    into nextid
    from sys.dual;
    :new.DepartId:=nextid;
  end if;
end tri_test_id;

OK,上面的代码就可以实现自动递增的功能了。

获取sequence序列的值:

create or replace function get_seq_next (seq_name in varchar2) return number
is
  seq_val number ;
begin
  execute immediate ‘select ‘|| seq_name|| ‘.nextval from dual‘ into seq_val ;
  return seq_val ;
end get_seq_next;
-- 创建获取序列下一个值的函数(得先获取下一个值后才能使用)
create or replace function get_seq_curr (seq_name in varchar2) return number
is
  seq_val number ;
begin
  execute immediate ‘select ‘|| seq_name|| ‘.currval from dual‘ into seq_val ;
  return seq_val ;
end get_seq_curr;

ORACLE实现自定义序列号生成

实际工作中,难免会遇到序列号生成问题,下面就是一个简单的序列号生成函数

(1)创建自定义序列号配置表如下:

--自定义序列
create table S_AUTOCODE
(
  pk1           VARCHAR2(32) primary key,
  atype         VARCHAR2(20) not null,
  owner         VARCHAR2(10) not null,
  initcycle     CHAR(1) not null,
  cur_sernum    VARCHAR2(50) not null,
  zero_flg      VARCHAR(2) not null,
  sequencestyle VARCHAR2(50),
  memo          VARCHAR2(60)
);
-- Add comments to the columns
comment on column S_AUTOCODE.pk1  is ‘主键‘;
comment on column S_AUTOCODE.atype  is ‘序列号类型‘;
comment on column S_AUTOCODE.owner  is ‘序列号所有者‘;
comment on column S_AUTOCODE.initcycle  is ‘序列号递增‘;
comment on column S_AUTOCODE.cur_sernum  is ‘序列号‘;
comment on column S_AUTOCODE.zero_flg  is ‘序列号长度‘;
comment on column S_AUTOCODE.sequencestyle  is ‘序列号样式‘;
comment on column S_AUTOCODE.memo  is ‘备注‘;
-- Create/Recreate indexes
create index PK_S_AUTOCODE on S_AUTOCODE (ATYPE, OWNER);

(2)初始化配置表,例如:

(3)自定义序列号生成函数:

 创建函数:SF_SYS_GEN_AUTOCODE
CREATE OR REPLACE FUNCTION SF_SYS_GEN_AUTOCODE(
          I_ATYPE IN VARCHAR2,  /*序列类别*/
          I_OWNER IN VARCHAR2   /*序列所有者*/
) RETURN VARCHAR2 IS
        /**************************************************************************************************/
        /* PROCEDURE NAME : SF_SYS_GEN_AUTOCODE                                                           */
        /* DEVELOPED BY   : WANGXF                                                                        */
        /* DESCRIPTION    : 主要用来生成自定义的序列号                                                    */
        /* DEVELOPED DATE : 2016-10-08                                                                    */
        /* CHECKED BY     :                                                                               */
        /* LOAD METHOD    : F1-DELETE INSERT                                                              */
        /**************************************************************************************************/

       O_AUTOCODE VARCHAR2(100);                        /*输出的序列号*/
       V_INITCYCLE S_AUTOCODE.INITCYCLE%TYPE;       /*序列号递增*/
       V_CUR_SERNUM S_AUTOCODE.CUR_SERNUM%TYPE;     /*序列号*/
       V_ZERO_FLAG S_AUTOCODE.ZERO_FLG%TYPE;        /*序列号长度*/
       V_SEQUENCESTYLE S_AUTOCODE.SEQUENCESTYLE%TYPE;/*序列号样式*/
       V_SEQ_NUM VARCHAR2(100);                     /*本次序列号*/
       V_DATE_YEAR CHAR(4);                         /*年份,如2016*/
       V_DATE_YEAR_MONTH CHAR(6);                   /*年份月份,如201610*/
       V_DATE_DATE CHAR(8);                         /*年份月份日,如20161008*/
       V_DATE_DATE_ALL CHAR(14);                    /*完整年份序列,如20161008155732*/

       /*
          支持的参数序列:
          $YEAR$ --> 年份
          $YEAR_MONTH$ --> 年份+月份,不含汉子
          $DATE$ --> 年份+月份+日期,不含汉子
          $DATE_ALL$ --> 完整日期,不含汉子
          $ORGAPP$ --> 所有者
          $SER$ --> 当前序列号
       */

       --解决查询事务无法执行DML的问题
       Pragma Autonomous_Transaction;
BEGIN
       -- 查询复核条件的序列号配置
       SELECT T.INITCYCLE,
              T.CUR_SERNUM,
              T.ZERO_FLG,
              T.SEQUENCESTYLE
              INTO V_INITCYCLE,V_CUR_SERNUM,V_ZERO_FLAG,V_SEQUENCESTYLE
       FROM S_AUTOCODE T WHERE T.ATYPE=I_ATYPE AND T.OWNER=I_OWNER ;

       --格式化当前日期
       SELECT
            TO_CHAR(SYSDATE,‘yyyy‘),
            TO_CHAR(SYSDATE,‘yyyyMM‘),
            TO_CHAR(SYSDATE,‘yyyyMMdd‘),
            TO_CHAR(SYSDATE,‘yyyyMMddHH24MISS‘)
            INTO  V_DATE_YEAR,V_DATE_YEAR_MONTH,V_DATE_DATE,V_DATE_DATE_ALL
       FROM DUAL;

       -- 日期处理
       O_AUTOCODE := REPLACE(V_SEQUENCESTYLE,‘$YEAR$‘,V_DATE_YEAR);
       O_AUTOCODE := REPLACE(O_AUTOCODE,‘$YEAR_MONTH$‘,V_DATE_YEAR_MONTH);
       O_AUTOCODE := REPLACE(O_AUTOCODE,‘$DATE$‘,V_DATE_DATE);
       O_AUTOCODE := REPLACE(O_AUTOCODE,‘$DATE_ALL$‘,V_DATE_DATE_ALL);

       --所有者处理
       O_AUTOCODE := REPLACE(O_AUTOCODE,‘$ORGAPP$‘,I_OWNER);

       --序号处理
       V_SEQ_NUM := TO_CHAR(TO_NUMBER(V_CUR_SERNUM)+TO_NUMBER(V_INITCYCLE));

       --反写当前序列号,确保每次都是递增
       UPDATE S_AUTOCODE T SET T.CUR_SERNUM=V_SEQ_NUM WHERE T.ATYPE=I_ATYPE AND T.OWNER=I_OWNER ;

       --不满足长度的前面补0
       IF LENGTH(V_SEQ_NUM) < TO_NUMBER(V_ZERO_FLAG)
         THEN
      /*
           LOOP
             V_SEQ_NUM := ‘0‘||V_SEQ_NUM;
           EXIT WHEN LENGTH(V_SEQ_NUM) = TO_NUMBER(V_ZERO_FLAG);
           END LOOP;
      */
       V_SEQ_NUM := LPAD(V_SEQ_NUM,TO_NUMBER(V_ZERO_FLAG),‘0‘);
       END IF;

       O_AUTOCODE := REPLACE(O_AUTOCODE,‘$SER$‘,V_SEQ_NUM);

       COMMIT;
       RETURN O_AUTOCODE;
EXCEPTION
       --如果没有对应的配置项,则返回ERROR值
       WHEN NO_DATA_FOUND THEN
         ROLLBACK;
         DBMS_OUTPUT.put_line(‘there is no config as you need...‘);
         RETURN ‘ERROR‘;
END SF_SYS_GEN_AUTOCODE;

(4)测试:

配置项:$YEAR$年$ORGAPP$质字第$SER$号
SELECT SF_SYS_GEN_AUTOCODE(‘ZDBCONTCN‘,‘012805‘) FROM DUAL;

(5) 结果

2016年012805质字第0200001号
时间: 2025-01-06 19:05:34

强制获取序列下一个值/当前值(oracle函数)的相关文章

获取第下一个兄弟元素 屏蔽浏览器的差异(nextElementsibling)

//获取element下一个兄弟元素 function getNextElementSibling(element){ //能力检测 判断是否支持nextElementSibling if(element.nextElementSibling){ return element.nextElementSibling; }else{ //获取下一个兄弟节点 var node = element.nextSibling; //如果没有下一个节点,此时null while(node && node

Jquery学习笔记:利用jquery获取select下拉框的值

jquery不是特别熟练,每次使用不常用的就要百度,特地记录下来. 我的下拉框是: <div class="form-group"> <select class="form-control" id="iv_level"> <option value="">店员</option> <option value="">店长</option>

js获取td下循环的input值

var value = document.getElementsByName("newQtyAdditinal"); for(var i =0;i<value.length;i++){  alert(value[i].value); } <tr class="tr_toggle" style="background: #FFFF99">       <td style="background: #FFFF99&q

获取指定元素的某一个样式属性值

1."元素.style.样式属性名" ->oDiv.style.height 弊端:"只能"获取在"行内"上编写过的样式,不管在哪些了对应的样式,只要没有在行内上写过,都获取不到 oDiv.style.height 由于height并没有写在行内样式上(写在样式表里了),所以获取的结果依然是"" 2.通过 window.getComputedStyle 获取所有经过浏览器计算的样式(只要的你的元素在浏览器加载的时候渲染过

php 获取数组第一个key 第一个键值对 等等

PHP 获取数组中的第一个元素或最后一个元素的值或者键值可以使用 PHP 自带的数组函数. PHP 获取数组中的第一个元素的值或者键值所使用的函数: current() - 返回数组中当前元素值(即:返回当前被数组内部指针指向的元素的值). reset() - 函数把数组的内部指针指向第一个元素,并返回这个元素的值. key() - 返回数组内部指针指向的元素的索引(即:键值). PHP 获取数组中的最后一个元素的值或者键值所使用的函数: end() - 函数将数组内部指针指向最后一个元素,并返

获取下拉框的值并通过拼接方式添加到td后面

html:<tr> <td class="Hint"><span class="color-red">*</span>选择分组:</td> <td width="40%"> <select id="groupId2" style="width: 80%;height: 30px"> <option th:if=&quo

[C++]LeetCode: 79 Next Permutation (下一个排列,常见面试题)

题目: Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). The repla

C++ Primer 学习笔记_41_STL实践与分析(15)--先来看看算法【下一个】

STL实践与分析 --初窥算法[下] 一.写容器元素的算法 一些算法写入元素值.在使用这些算法写元素时一定要当心.必须确保算法所写的序列至少足以存储要写入的元素. 1.写入输入序列的元素 写入到输入序列的算法本质上是安全的--仅仅会写入与指定输入范围数量同样的元素. 写入到输入序列的一个简单算法是fill函数: fill(iVec.begin(),iVec.end(),10); fill(iVec.begin(),iVec.begin()+iVec.size()/2,0); fill带有一对迭代

数据结构——栈——寻找下一个较大元素

题目描述 给出一个数组,向右寻找每一个元素的下一个较大的元素,没有更大的则为-1 举例 {4,6,1,3,2,5} 则求得的答案应为 {6,-1,3,5,5,-1} 题目分析 首先对于这样的题目,我们总是先想到最简单的,那么就是枚举,每次循环一个元素,不停的向右找就可以了.时间复杂度应该是n^2 但是这样肯定是不够用的. 然后我们考虑,这道题我们实际上遇到的问题是什么? 其实简单的说,这道题的意思是,在变化的数组中找到下一个较大的值. 难点在于,数组元素的变化,以及不是找最大值,而是找下一个较大