Oracle中Nextval用法SEQUENCE与SYS_GUID()

  • Post author:
  • Post category:其他




名称

CREATE SEQUENCE -- 创建一个新的序列发生器



语法

CREATE [ TEMPORARY | TEMP ] SEQUENCE name [ INCREMENT [ BY ] increment ]
    [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
    [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
    [ OWNED BY { table.column | NONE } ]



描述


CREATE SEQUENCE

将向当前数据库里增加一个新的序列号生成器。 包括创建和初始化一个新的名为 name的单行表。生成器将为使用此命令的用户所有。

如果给出了一个模式名,那么该序列是在指定模式中创建的。 否则它会在当前模式中创建临时序列存在于一个特殊的模式中,因此如果创建一个临时序列的时候, 不能给出模式名。 序列名必需和同一模式中的其他序列,表,索引,或者视图不同。

在创建序列后,你可以使用

nextval, currval, setval

函数操作序列。。这些函数在 Section 9.12 中有详细文档。

尽管你不能直接更新一个序列,但你可以使用象

SELECT * FROM name;

检查一个序列的参数和当前状态。特别是序列的

last_value

字段显示了任意后端进程分配的最后的数值。 (当然,这些值在被打印出来的时候可能已经过时了 — 如果其它进程正积极地使用

nextval

。)



参数


TEMPORARY



TEMP

如果声明了这个修饰词,那么该序列对象只为这个会话创建, 并且在会话结束的时候自动删除。在临时序列存在的时候, 同名永久序列是不可见的(在同一会话里),除非它们是用模式修饰的名字引用的。

www.2cto.com

name

将要创建的序列号名(可以用模式修饰)。

increment

可选子句

INCREMENT BY increment

要创建一个新的值,应该向当前序列值上增加什么。一个正数将生成一个递增的序列, 一个负数将生成一个递减的序列。缺省值是一(1)。

minvalue

NO MINVALUE

可选的子句

MINVALUE minvalue

决定一个序列可生成的最小值。 如果没有声明这个子句或者声明了

NO MINVALUE

,那么就使用缺省。 缺省分别是递增序列为 1 递减为 -263-1。

maxvalue

NO MAXVALUE

使用可选子句

MAXVALUE maxvalue

决定序列的最大值。 如果没有声明这个子句或者声明了

NO MAXVALUE

,那么就使用缺省。 缺省的分别是递增为 -263-1,递减为 -1。

start

可选的

START WITH start

子句 使序列可以从任意位置开始。缺省初始值是递增序列为

minvalue

递减序列为

maxvalue

.

cache

CACHE cache 选项使序列号预分配并且为快速访问存储在内存里面。 最小值(也是缺省值)是1(一次只能生成一个值, 也就是说没有缓存)这也是缺省。

CYCLE

NO CYCLE

可选的CYCLE关键字可用于使序列到达 最大值(maxvalue) 或 最小值(minvalue) 时可复位并继续下去。如果达到极限,生成的下一个数据将分别是 最小值(minvalue) 或 最大值(maxvalue)。

如果声明了可选的关键字

NO CYCLE

, 那么在序列达到其最大值之后任何对

nextval

的调用都强返回一个错误。 如果既没有声明

CYCLE

也没有声明

NO CYCLE

, 那么

NO CYCLE

是缺省。



注意

使用

DROP SEQUENCE

语句来删除序列。

序列是基于

bigint

运算的,因此其范围不能超过八字节的整数范围(

-9223372036854775808



9223372036854775807

)。 在一些老一点的平台上可能没有对八字节整数的编译器支持, 这种情况下序列使用普通的

integer

运算(范围是

-2147483648



+2147483647

)。

如果

cache

设置大于一, 并且这个序列对象将被用于并发多会话的场合,那么可能会有不可预料的结果发生。 每个会话在一次访问序列对象的过程中将分配并缓存随后的序列值,并且相应增加序列对象的

last_value

。 这样,同一个事务中的随后的

cache-1



nextval

将只是返回预先分配的数值,而不用动序列对象。因此,任何在一个会话中分配但是没有使用的数字都将在会话结尾丢失,导致序列里面出现”空洞”。

另外,尽管系统保证为多个会话分配独立的序列值,但是如果考虑所有会话, 那么这个数值可能会丢失顺序。比如,如果

cache

设置为

10

,那么会话 A 保留了 1…10 并且返回

nextval=1

, 然后会话 B 可能会保留 11…20 然后在会话 A 生成

nextval=2

之前返回

nextval=11

。因此,对于

cache

设置为一的情况,我们可以安全地假设

nextval

值是顺序生成的; 而如果把

cache

设置得大于一, 那么你只能假设

nextval

值总是唯一得,而不是完全顺序地生成。 同样,

last_value

将反映任何会话保留的最后的数值,不管它是否曾被

nextval

返回。

另外一个考虑是在这样的序列上执行的

setval

将不会被其它会话注意到,直到它们用光他们缓存的数值。



例子

创建一个叫 serial 的递增序列,从101开始:

CREATE SEQUENCE serial START 101;

从此序列中选出下一个数字:

SELECT nextval ('serial'); 

nextval 
------- 
114

在一个 INSERT 中使用此序列:

INSERT INTO distributors VALUES (nextval('serial'),'nothing');

在一个

COPY FROM

后更新序列:

BEGIN;
COPY distributors FROM 'input_file'; SELECT setval('serial', max(id)) FROM distributors; 
END;



兼容性


CREATE SEQUENCE

在 SQL:2003 里声明。

PostgreSQL 遵循标准,只有下面的例外:

  • 还不支持标准的

    AS <数据类型>

    表达式。
  • 获取下一个数值是用

    nextval()

    函数不是标准的,而标准是用

    NEXT VALUE FOR 表达式


  • OWNED BY

    子句是 PostgreSQL 的扩展



Oracle 中

Nextval

用法


SQL Server

,

Sybase

:

有個

identity

屬性可以讓系統自動增1

CREATE TABLE a 
  ( 
     a1 INT IDENTITY(1, 1), 
     a2 VARCHAR(6) 
  ) 

然後在insert時:

insert   into   a   values( 'hello! '); --不用管a1,系統會幫你自動增1

Oracle:

使用

SEQUENCE(序列)

可以達到你的要求

CREATE TABLE a 
  ( 
     a1 INT, 
     a2 VARCHAR2(6) 
  ); 

CREATE SEQUENCE seq_a 
  INCREMENT BY 1; 

然後在insert時:

insert   into   a   values(seq_a.nextval, 'hello! '); --seq_a.nextval是該序列的下個值



ORACLE利用

Sequence

实现字段自增长

在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;

一旦定义了

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 emp VALUES

(empseq.nextval, 'LEWIS', 'CLERK',7902, SYSDATE, 1200, NULL, 20);

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;



SYS_GUID()与sequence的比较

列生成器

sequence

所生成的数字只能保证在单个实例里是唯一的,这就不适合将它用作并行或者远程环境里的主关键字,因为各自环境里的序列可能会生成相同的数字,从而导致冲突的发生。


SYS_GUID

会保证它创建的标识符在每个数据库里都是唯一的。

此外,序列必须是DML陈述式的一部分,因此它需要一个到数据库的往返过程(否则它就不能保证其值是唯一的)。


SYS_GUID

源自不需要对数据库进行访问的时间戳和机器标识符,这就节省了查询的消耗。

  create table use_seq_table(id integer);

  create sequence use_seq_sequence;

  insert into use_seq_table values (use_seq_sequence.nextval);

  
  create table use_guid_table(id raw(16));

  insert into use_guid_table(sys_guid());

对象在不同机器的不同数据库里生成以及需要将数据合并到一起的情况下,

SYS_GUID

很有用。


SYS_GUID()



sequence

的作用及用法基本相同,都可以放在bi触发器中使用。

-- Create sequence

create sequence SEQ_ADDRESS

minvalue 1    

maxvalue 999999999999999999999999999

start with 1

increment by 1

nocache;

create or replace trigger tri_address_bi before insert on address for each row

begin

 if :new.id<0 or :new.id is null then

  select seq_address.nextval into :new.id from dual;

      --select substr(sys_guid(),1,32) into :new.id from dual;

 end if;

end;

/   



使用限制:


SYS_GUID

生成的值的另一个显著的不足之处是,管理这些值会变得困难得多。你必须(手动)输入它们或者通过脚本来填充它们,或者将它们作为Web参数来传递。

出于这些原因,将

SYS_GUID

作为一个主关键字不是一个很好主意,除非是在一个并行的环境里或者希望避免使用管理序列生成器的情况下。

不过,使用

SYS_GUID

来做主键也不是不可以,但需要先转为

varchar2

较好。最好在使用时显示转换一下,如:

substr(sys_guid(),1,32)

,直接使用

RAW

显然是不合适的。

直接插

raw

进入

varchar2

字段,发生隐式的转换,总不是太妥。曾见过因为大量隐式转换导致最后数据库崩溃,当然事后看是数据库的

bug

了。