SQL Server SEQUENCE 序列详解:创建、使用与管理
SQL Server 自 2012 版本引入 SEQUENCE(序列)对象,它提供了一种独立于表的数值生成机制。相比传统的 IDENTITY 列,SEQUENCE 更加灵活,支持多表共享、循环递增和批量预取。本文将详细介绍如何创建、使用及维护序列。
序列的优势与应用场景
在 SQL Server 2012 之前,生成唯一标识通常依赖 GUID 或 IDENTITY 列。SEQUENCE 的出现解决了以下特定需求:
- 预分配编号:应用程序可在 INSERT 之前获取下一个值,而 IDENTITY 必须在插入行时生成。
- 多表共享:多个表或多个列可以共用同一个序列号源。
- 循环复用:当数值达到上限后,可配置自动重置从最小值继续(例如 1 到 10 循环)。
- 自定义排序:结合
NEXT VALUE FOR ... OVER (ORDER BY ...)子句,可按指定逻辑生成序号。 - 批量获取:使用
sp_sequence_get_range一次性获取多个连续序列号,减少事务锁竞争。
注意限制:序列不支持事务回滚(回滚后序号依然增加),也不支持数据库复制。
第一步:创建序列 CREATE SEQUENCE
可以通过图形界面 SSMS 或脚本创建序列。创建时需指定数据类型、起始值、步长(增量)、最大值/最小值以及是否循环。如果未指定类型,默认为 bigint。
1. 基本序列设置
默认整数序列:从 -2,147,483,648 开始,每次增加 1。
CREATE SEQUENCE Schema.SequenceName
AS int
INCREMENT BY 1 ;类 Identity 序列:从 1 开始递增,常用于替代传统自增列。
CREATE SEQUENCE Schema.SequenceName
AS int
START WITH 1
INCREMENT BY 1 ;高级配置(含循环):创建一个 Decimal 类型序列,范围 100-200,步长为 25,达到 200 后回到 100。
CREATE SEQUENCE Test.DecSeq
AS decimal(3,0)
START WITH 125
INCREMENT BY 25
MINVALUE 100
MAXVALUE 200
CYCLE
CACHE 3 ;第二步:使用序列号
核心函数为 NEXT VALUE FOR sequence_name。调用此函数会立即消耗当前序列值。
1. 在 INSERT 语句中使用
将序列生成的值直接作为主键或业务编号插入表中:
-- 创建架构和测试表
CREATE SCHEMA Test;
GO
CREATE TABLE Test.Orders (
OrderID int PRIMARY KEY,
Name varchar(20) NOT NULL,
Qty int NOT NULL);
GO
-- 创建从1开始的序列
CREATE SEQUENCE Test.CountBy1
START WITH 1
INCREMENT BY 1 ;
GO
-- 插入记录时调用 NEXT VALUE FOR
INSERT Test.Orders (OrderID, Name, Qty)
VALUES (NEXT VALUE FOR Test.CountBy1, 'Tire', 2);
INSERT Test.Orders (OrderID, Name, Qty)
VALUES (NEXT VALUE FOR Test.CountBy1, 'Seat', 1);
INSERT Test.Orders (OrderID, Name, Qty)
VALUES (NEXT VALUE FOR Test.CountBy1, 'Brake', 1);
GO
SELECT * FROM Test.Orders ;2. 在 SELECT 查询中动态生成
可用于报表编号或临时分组:
SELECT NEXT VALUE FOR CountBy5 AS SurveyGroup, Name FROM sys.objects ;
3. 结合 ORDER BY 定制序号
如果不希望严格按照物理生成顺序,而是按字母或其他字段排序生成序号:
SELECT NEXT VALUE FOR Samples.IDLabel OVER (ORDER BY Name) AS NutID,
ProductID, Name, ProductNumber
FROM Production.Product
WHERE Name LIKE '%nut%';4. 批量获取数值范围
使用系统存储过程 sp_sequence_get_range 同时获取多个序号,避免逐次调用的开销:
DECLARE @range_first_value_output sql_variant; EXEC sys.sp_sequence_get_range @sequence_name = N'Test.RangeSeq' , @range_size = 4 , @range_first_value = @range_first_value_output OUTPUT; SELECT @range_first_value_output AS FirstNumber;
5. 将现有 Identity 列迁移为 Sequence
若要将原有的自增列改为由序列控制,建议先在原表新增一列,复制旧值到新列,然后删除旧列并重新建立约束。最后为该新列绑定序列作为默认值:
-- 1. 添加新列并复制数据
ALTER TABLE Test.Department
ADD DepartmentIDNew smallint NULL;
GO
UPDATE Test.Department SET DepartmentIDNew = DepartmentID;
GO
-- 2. 删除旧列(需先删约束)
ALTER TABLE Test.Department DROP CONSTRAINT [PK_Department_DepartmentID];
ALTER TABLE Test.Department DROP COLUMN DepartmentID;
GO
-- 3. 重命名新列为原名列,设为非空
EXEC sp_rename 'Test.Department.DepartmentIDNew', 'DepartmentID', 'COLUMN';
ALTER TABLE Test.Department ALTER COLUMN DepartmentID smallint NOT NULL;
ALTER TABLE Test.Department
ADD CONSTRAINT PK_Department_DepartmentID PRIMARY KEY CLUSTERED (DepartmentID ASC);
GO
-- 4. 创建序列并绑定为默认值
-- 先获取当前最大ID
SELECT MAX(DepartmentID) FROM Test.Department;
-- 假设当前最大值为3,序列从4开始
CREATE SEQUENCE Test.DeptSeq
AS smallint
START WITH 4
INCREMENT BY 1;
GO
ALTER TABLE Test.Department
ADD CONSTRAINT DefSequence DEFAULT (NEXT VALUE FOR Test.DeptSeq) FOR DepartmentID;
GO第三步:管理与维护序列
1. 修改/重置序列 ALTER SEQUENCE
可暂停、更改步长或重置起点:
ALTER SEQUENCE Samples.IDLabel RESTART WITH 1 ;
2. 删除序列 DROP SEQUENCE
注意:如果该序列被表中的列默认值引用,则无法直接删除,必须先移除依赖关系。
DROP SEQUENCE CountBy1 ;
3. 查看序列状态
查询系统视图 sys.sequences 以确认缓存大小和当前值:
SELECT cache_size, current_value FROM sys.sequences WHERE name = 'DecSeq' ;
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













