Oracle sequence NEXTVAL和CURRVAL
创建好序列之后,要引用序列中递增的值,需要使用Oracle的伪列。伪列的行为和表列的行为比较相似,但是并没有实际存储到表中。对序列来说,通常使用NEXTVAL和CURRVAL伪列获取其序列的值。
-
NEXTVAL:
获取序列下一个值,若是创建新的序列,那么第一次调用返回的是START WITH 指定的值,
以后每次调用都会的得到当前序列值加上步长后的数字,序列会根据序列最后生成的数字加上步进来得到。
NEXTVAL会导致序列发生步进,序列是不能回退的。 -
CURRVAL:
获取序列当前值,即:最后一次调用NEXTVAL后生成的数字。
CURRVAL不会导致步进。但是新创建的序列至少调用一次NEXTVAL生成一个值后才可以使用CURRVAL。
序列通常使用NEXTVAL获取到序列的初始值,后续调用NEXTVAL时会按照序列定义的步进值进行递增,在使用NEXTVAL获取序列的初始值之后,才能使用CURRVAL返回序列的当前值,这个值是有NECTVA计算返回的。直接使用CURRVAL 会报错 > ORA-08002: sequence YEWUBH.CURRVAL is not yet defined in this session 。
在一些地方不能使用序列,会导致Oracle抛出异常,不能使用序列的场合如下:
- 查询视图时的SELECT列表。
- 具有DISTINCT关键字的SELECT语句。
- 具有GROUP BY、HAVING 或 ORDER BY 字句的SELECT 语句。
- 位于SELECT、DELETE 或UPDATE 语句的字句。
- 在CREATE TABLE 或 ALTER TABLE语句的DEFAULT。
此时并未重视 sequence 的使用,与postgresql 中的序列进行了对比
postgresql sequence
下面的几个需要重点关注:
- 使用 currval 函数可以返回最近一次使用nextval 获得的指定序列的数值。
- lastval 函数与currval 函数的不同之处在于,不管最后调用的是哪个序列,总返回最后一次调用nextval 函数返回的值。
- setval 函数能够改变序列的当前值, 然后再调用nextval 函数时,可能返回的值会变成改变后的当前值+1
- 在事务中使用序列,当事务回滚后,序列不会回滚,序列会出现“空洞”现象
主要涉及到的函数是:
| 函数 | 返回类型 | 描述 |
|---|---|---|
| nextval(regclass) | bigint | 递增序列对象到它的下一个数值并且返回该值。这个动作是自动完成的。即使多个会话并发运行nextval,每个进程也会安全地收到一个唯一的序列值。 |
| currval(regclass) | bigint | 在当前会话中返回最近一次nextval抓到的该序列的数值。(如果在本会话中从未在该序列上调用过 nextval,那么会报告一个错误。)请注意因为此函数返回一个会话范围的数值,而且也能给出一个可预计的结果,因此可以用于判断其它会话是否执行过nextval。 |
| lastval() | bigint | 返回当前会话里最近一次nextval返回的数值。这个函数等效于currval,只是它不用序列名为参数,它抓取当前会话里面最近一次nextval使用的序列。如果当前会话还没有调用过nextval,那么调用lastval将会报错。 |
| setval(regclass, bigint) | bigint | 重置序列对象的计数器数值。设置序列的last_value字段为指定数值并且将其is_called字段设置为true,表示下一次nextval将在返回数值之前递增该序列。 |
| setval(regclass, bigint, boolean) | bigint | 重置序列对象的计数器数值。功能等同于上面的setval函数,只是is_called可以设置为true或false。如果将其设置为false,那么下一次nextval将返回该数值,随后的nextval才开始递增该序列。 |
序列函数为用户从序列对象中获取后续的序列值提供了简单的多用户安全的方法。
1.nextval(regclass)
描述:递增序列并返回新值。
为了避免从同一个序列获取值的并发事务被阻塞,nextval操作不会回滚;也就是说,一旦一个值已经被抓取,那么就认为它已经被用过了,并且不会再被返回。即使该操作处于事务中,当事务之后中断,或者如果调用查询结束不使用该值,也是如此。这种情况将在指定值的顺序中留下未使用的“空洞”。因此,openGauss序列对象不能用于获得“无间隙”序列。
nextval函数只能在主机上执行,备机不支持执行此函数。
nextval函数有两种调用方式(其中第二种调用方式目前不支持Sequence命名中有特殊字符".“的情况),如下:
bytehouse=# select nextval('seqDemo');
nextval
---------
2
(1 row)
bytehouse=# select seqDemo.nextval;
nextval
---------
2
(1 row)
2.currval(regclass)
返回当前会话里最近一次nextval返回的指定的sequence的数值。如果当前会话还没有调用过指定的sequence的nextval,那么调用currval将会报错。
currval函数有两种调用方式(其中第二种调用方式目前不支持Sequence命名中有特殊字符”.“的情况),如下:
bytehouse=# select currval('seq1');
currval
---------
2
(1 row)
bytehouse=# select seq1.currval;
currval
---------
2
(1 row)
3.lastval()
返回当前会话里最近一次nextval返回的数值。这个函数等效于currval,只是它不用序列名为参数,它抓取当前会话里面最近一次nextval使用的序列。如果当前会话还没有调用过nextval,那么调用lastval将会报错。
bytehouse=# select lastval();
lastval
---------
2
(1 row)
4.setval(regclass,numeric)
设置序列的当前数值。
bytehouse=# select setval('seqDemo',1);
setval
--------
1
(1 row)
5.setval(regclass, numeric, Boolean)
设置序列的当前数值以及is_called标志。
bytehouse=# select setval('seqDemo',1,true);
setval
--------
1
(1 row)
setval后当前会话会立刻生效,但如果其他会话有缓存的序列值,只能等到缓存值用尽才能感知Setval的作用。所以为了避免序列值冲突,setval要谨慎使用。 因为序列是非事务的,setval造成的改变不会由于事务的回滚而撤销。
setval函数只能在主机上执行,备机不支持执行此函数。
6.pg_sequence_last_value(sequence_oid oid, OUT cache_value int16, OUT last_value int16)
获取指定sequence的参数,包含缓存值,当前值。
bytehouse=# select * from pg_sequence_last_value('seqDemo'::regclass);
cache_value | last_value
-------------+------------
20 | 120
(1 row)
7.last_insert_id()
获取最近一次为自动增长列成功插入的第一个自动生成的值。
8.last_insert_id(int16)
设置下一次last_insert_id()函数的返回值,并返回此值。若参数为NULL,将下一次last_insert_id()函数的返回值设为0,此函数返回NULL。
bytehouse=# select last_insert_id(100);
last_insert_id
----------------
100
(1 row)
bytehouse=# select last_insert_id();
last_insert_id
----------------
100
(1 row)
last_insert_id()和last_insert_id(int16)是会话级别的函数,若当前会话未对自动增长列插入任何数据,last_insert_id()返回值为0。




