名称
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
用法
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
实现字段自增长
Sequence
在oracle中
sequence
就是所谓的序列号,每次取的时候它会自动增加,一般用在需要按序列号排序的地方。
1、
Create Sequence
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
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
了。