众所周知,在之前的SQL SERVER版本中,一般采用GUID或者IDENTITY来作为标示符,但是IDENTITY是一个表对象,只能保证在一张表里面的序列,当我们遇到以下情况时,
如上表,我们需要在多表之间,实现ID的一致性,在SQL SERVER里面就会有一定的麻烦,通常我们会使用额外使用一张TEMP表来映射这些ID的关系然后再从中取序列来完成。
SEQUENCE在ORACLE中其实很早就存在了,SQL SERVER 2012的SEQUENCE功能和那个相似,是一个基于SCHEMA的对象,所以可以被多表调用。
序列是用户定义的绑定到架构的对象,该对象可根据创建序列所依据的规范来生成数值序列。 这组数值以定义的间隔按升序或降序生成,并且可配置为用尽时重新启动(循环)。 序列不与特定表相关联,这一点与标识列不同。 应用程序将引用某一序列对象以便检索其下一个值。 序列与表之间的关系由应用程序控制。 用户应用程序可以引用一个序列对象,并跨多个行和表协调值。与在插入行时生成的标识列值不同,应用程序可以获得下一个序列号,而不必通过调用 NEXT VALUE FOR 函数来插入行。 使用 sp_sequence_get_range 同时获取多个序列号。
SEQUENCE语法如下: (创建一个序列对象并指定其属性)
CREATE SEQUENCE [schema_name . ] sequence_name [ AS [ built_in_integer_type | user-defined_integer_type ] ] [ START WITH <constant> ] [ INCREMENT BY <constant> ] [ { MINVALUE [ <constant> ] } | { NO MINVALUE } ] [ { MAXVALUE [ <constant> ] } | { NO MAXVALUE } ] [ CYCLE | { NO CYCLE } ] [ { CACHE [ <constant> ] } | { NO CACHE } ] [ ; ]
sequence_name 指定数据库中标识序列的唯一名称。 类型为 sysname。
[ built_in_integer_type | user-defined_integer_type 序列可定义为任何整数类型。如果未提供任何数据类型,则默认 bigint类型。
START WITH 默认值为 CACHE。
ORACLE中有SEQUENCE的功能,SQL SERVER类似的功能使用IDENTITY列实现,但是有很大的局限性。在2012中,微软终于增加了 SEQUENCE 对象,功能和性能都有了很大的提高。
我们可以在SSMS中创建也可以使用SQL SERVER脚本创建序列对象:
使用SQL创建序列对象:
IF EXISTS(SELECT * FROM sys.sequences WHERE name = N'TestSeq') DROP SEQUENCE TestSeq; GO --创建序列对象 CREATE SEQUENCE TestSeq AS TINYINT START WITH 1 INCREMENT BY 1; GO --创建表 CREATE TABLE TEST(ID tinyint, Name varchar(150)) --产生序列号码并插入表中 INSERT INTO TEST(ID,Name) VALUES(NEXT VALUE FOR TestSeq, 'allen') INSERT INTO TEST(ID,Name) VALUES(NEXT VALUE FOR TestSeq, 'kevin') SELECT * FROM TEST
--产生序列可以重复使用,下面的例子当序列号码超过255后又重新从0开始。 CREATE SEQUENCE [dbo].[Test1Seq] AS [tinyint] START WITH 0 INCREMENT BY 5 CYCLE SELECT NEXT VALUE FOR [Test1Seq]
--重新将序列初始值变为5 ALTER SEQUENCE dbo.TestSeq RESTART WITH 5; SELECT * FROM sys.sequences WHERE name = 'TestSeq'
--共享序列,两个表可以使用同一个序列对象(IDENTITY列是不可以的) CREATE SEQUENCE dbo.Seq AS INT START WITH 1 INCREMENT BY 1 CREATE TABLE dbo.Examp1 ( Seq INT NOT NULL, Name VARCHAR(50) NOT NULL ); CREATE TABLE dbo.Examp2 ( Seq INT NOT NULL, Name VARCHAR(50)NOTNULL ); INSERT INTO dbo.Examp1(Seq,Name) VALUES (NEXT VALUE FOR dbo.Seq, 'Tom'); INSERT INTO dbo.Examp2(Seq,Name) VALUES (NEXT VALUE FOR dbo.Seq, 'Jerry'); SELECT * FROM Examp1 SELECT * FROM Examp2
--可以直接在查询中使用序列对象(IDENTITY列是不可以的) CREATE SEQUENCE SeqOrder AS tinyint START WITH1 INCREMENT BY1 MINVALUE 1 NO MAXVALUE CYCLE; GO SELECT ID, Name,NEXT VALUE FOR SeqOrder OVER(ORDER BY Name DESC) AS [Order] FROM test;
为了提升性能,还可以使用CACHE选项,这样就可以将序列号码缓存到内存,减少IO操作,值得一提的是序列对象可以指定最大值和最小值,增加值可以为负数。