NEXT VALUE FOR (Transact-SQL)
通过指定的序列对象生成序列号。
有关创建和使用序列的完整讨论,请参阅序列号。 可以使用 sp_sequence_get_range 保留一定范围内的序列号。
语法
NEXT VALUE FOR [ database_name . ] [ schema_name . ] sequence_name
[ OVER (<over_order_by_clause>) ]
参数
database_name
包含序列对象的数据库的名称。schema_name
包含序列对象的架构的名称。sequence_name
生成该编号的序列对象的名称。over_order_by_clause
确定将序列值分配给分区中的行的顺序。 有关详细信息,请参阅 OVER 子句 (Transact-SQL)。
返回类型
使用序列类型返回一个数字。
注释
可以在存储过程和触发器中使用 NEXT VALUE FOR 函数。
在查询或默认约束中使用 NEXT VALUE FOR 函数时,如果多次使用相同的序列对象,或者在提供这些值的语句以及执行的默认约束中使用相同的序列对象,则为结果集的行中引用同一序列的所有列返回相同的值。
NEXT VALUE FOR 函数具有不确定性,只允许在明确定义了生成的序列值数目的上下文中使用。 下面定义了给定语句中的每个引用的序列对象使用的值数目:
SELECT - 对于每个引用的序列对象,将为语句结果中的每一行生成一个新值。
INSERT … VALUES - 对于每个引用的序列对象,将为语句中的每一个插入行生成一个新值。
UPDATE - 对于每个引用的序列对象,将为语句所更新的每一行生成一个新值。
过程语句(如 DECLARE、SET 等)- 对于每个引用的序列对象,将为每个语句生成一个新值。
限制和局限
不能在下列情况下使用 NEXT VALUE FOR 函数:
数据库处于只读模式时。
作为表值函数的参数。
作为聚合函数的参数。
在子查询中,包括公用表表达式和派生表。
在视图、用户定义的函数或计算列中。
在使用 DISTINCT、UNION、UNION ALL、EXCEPT 或 INTERSECT 运算符的语句中。
在使用 ORDER BY 子句的语句中(除非使用 NEXT VALUE FOR … OVER (ORDER BY …))。
在以下子句中:FETCH、OVER、OUTPUT、ON、PIVOT、UNPIVOT、GROUP BY、HAVING、COMPUTE、COMPUTE BY 或 FOR XML。
在使用 CASE、CHOOSE、COALESCE、IIF、ISNULL 或 NULLIF 的条件表达式中。
在不属于 INSERT 语句的 VALUES 子句中。
在检查约束的定义中。
在规则或默认对象的定义中。 (它可用于默认约束。)
作为用户定义表类型中的默认值。
在使用 TOP、OFFSET 或设置了 ROWCOUNT 选项的语句中。
在语句的 WHERE 子句中。
在 MERGE 语句中。 (在目标表的默认约束中使用 NEXT VALUE FOR 函数并且在 MERGE 语句的 CREATE 语句中使用默认值的情况下例外。)
在默认约束中使用序列对象
在默认约束中使用 NEXT VALUE FOR 函数时,下列规则适用:
可以从多个表的默认约束中引用单个序列对象。
表和序列对象必须位于同一数据库中。
添加默认约束的用户必须对序列对象具有 REFERENCES 权限。
在删除默认约束之前,无法删除从默认约束中引用的序列对象。
如果多个默认约束使用相同的序列对象,或者在提供这些值的语句以及执行的默认约束中使用相同的序列对象,则为行中的所有列返回相同的序列号。
默认约束中对 NEXT VALUE FOR 函数的引用不能指定 OVER 子句。
可以更改默认约束中引用的序列对象。
如果 INSERT … SELECT 或 INSERT … EXEC 语句中插入的数据来自使用 ORDER BY 子句的查询,则按照 ORDER BY 子句指定的顺序生成 NEXT VALUE FOR 函数返回的值。
通过 OVER ORDER BY 子句使用序列对象
通过将 OVER 子句应用于 NEXT VALUE FOR 调用,NEXT VALUE FOR 函数支持生成排序的序列值。 通过使用 OVER 子句,可以向用户保证返回的值是按照 OVER 子句的 ORDER BY 子子句的顺序生成的。 将 NEXT VALUE FOR 函数与 OVER 子句一起使用时,下列附加规则适用:
如果在单个语句中为相同序列生成器多次调用 NEXT VALUE FOR 函数,这些调用必须使用相同的 OVER 子句定义。
如果在单个语句中多次调用 NEXT VALUE FOR 函数以引用不同的序列生成器,则这些调用可以具有不同的 OVER 子句定义。
为 NEXT VALUE FOR 函数应用的 OVER 子句不支持 PARTITION BY 子子句。
如果 SELECT 语句中对 NEXT VALUE FOR 函数的所有调用均指定 OVER 子句,则可以在 SELECT 语句中使用 ORDER BY 子句。
在 SELECT 语句或 INSERT … SELECT … 语句中使用时,允许将 OVER 子句与 NEXT VALUE FOR 函数一起使用。 不允许在 UPDATE 或 MERGE 语句中使用 NEXT VALUE FOR 函数。
如果另一个进程同时访问序列对象,则返回的编号可能会出现间断。
元数据
有关序列的信息,请查询 sys.sequences 目录视图。
安全性
权限
要求对序列对象或序列的架构具有 UPDATE 权限。 有关授予权限的示例,请参阅本主题后面的示例 F。
所有权链接
序列对象支持所有权链接。 如果序列对象具有与调用存储过程、触发器或表相同的所有者(将序列对象作为默认约束),则不需要对序列对象进行权限检查。 如果序列对象与调用存储过程、触发器或表归不同的用户所有,则需要对序列对象进行权限检查。
如果在表中将 NEXT VALUE FOR 函数作为默认值,则用户需要对表具有 INSERT 权限并且对序列对象具有 UPDATE 权限,才能使用默认值插入数据。
如果默认约束具有与序列对象相同的所有者,则在调用默认约束时不需要具有序列对象的权限。
如果默认约束和序列对象归不同的用户所有,即使通过默认约束调用序列对象,也需要具有序列对象的权限。
审核
若要审核 NEXT VALUE FOR 函数,请监视 SCHEMA_OBJECT_ACCESS_GROUP。
示例
有关创建序列和使用 NEXT VALUE FOR 函数生成序列号的示例,请参阅序列号。
以下示例在名为 Test 的架构中使用名为 CountBy1 的序列。 将执行以下语句以创建 Test.CountBy1 序列。 示例 C 和 E 使用 AdventureWorks2012 数据库,因此,将在该数据库中创建 CountBy1 序列。
USE AdventureWorks2012 ;
GO
CREATE SCHEMA Test;
GO
CREATE SEQUENCE Test.CountBy1
START WITH 1
INCREMENT BY 1 ;
GO
A.在 SELECT 语句中使用序列
以下示例创建一个名为 CountBy1 的序列,每次使用该序列时将增加 1。
SELECT NEXT VALUE FOR Test.CountBy1 AS FirstUse;
SELECT NEXT VALUE FOR Test.CountBy1 AS SecondUse;
下面是结果集:
FirstUse
1
SecondUse
2
B.将变量设置为下一个序列值
以下示例介绍了三种将变量设置为下一个序列号值的方法。
DECLARE @myvar1 bigint = NEXT VALUE FOR Test.CountBy1
DECLARE @myvar2 bigint ;
DECLARE @myvar3 bigint ;
SET @myvar2 = NEXT VALUE FOR Test.CountBy1 ;
SELECT @myvar3 = NEXT VALUE FOR Test.CountBy1 ;
SELECT @myvar1 AS myvar1, @myvar2 AS myvar2, @myvar3 AS myvar3 ;
GO
C.将序列与排名窗口函数一起使用
USE AdventureWorks2012 ;
GO
SELECT NEXT VALUE FOR Test.CountBy1 OVER (ORDER BY LastName) AS ListNumber,
FirstName, LastName
FROM Person.Contact ;
GO
D.在默认约束定义中使用 NEXT VALUE FOR 函数
支持在默认约束定义中使用 NEXT VALUE FOR 函数。 有关在 CREATE TABLE 语句中使用 NEXT VALUE FOR 的示例,请参阅序列号中的示例 C。 以下示例使用 ALTER TABLE 将序列作为默认值添加到当前表中。
CREATE TABLE Test.MyTable
(
IDColumn nvarchar(25) PRIMARY KEY,
name varchar(25) NOT NULL
) ;
GO
CREATE SEQUENCE Test.CounterSeq
AS int
START WITH 1
INCREMENT BY 1 ;
GO
ALTER TABLE Test.MyTable
ADD
DEFAULT N'AdvWorks_' +
CAST(NEXT VALUE FOR Test.CounterSeq AS NVARCHAR(20))
FOR IDColumn;
GO
INSERT Test.MyTable (name)
VALUES ('Larry') ;
GO
SELECT * FROM Test.MyTable;
GO
E.在 INSERT 语句中使用 NEXT VALUE FOR 函数
以下示例创建一个名为 TestTable 的表,然后使用 NEXT VALUE FOR 函数插入一行。
CREATE TABLE Test.TestTable
(CounterColumn int PRIMARY KEY,
Name nvarchar(25) NOT NULL) ;
GO
INSERT Test.TestTable (CounterColumn,Name)
VALUES (NEXT VALUE FOR Test.CountBy1, 'Syed') ;
GO
SELECT * FROM Test.TestTable;
GO
E.将 NEXT VALUE FOR 函数与 SELECT … INTO 一起使用
以下示例使用 SELECT … INTO 语句创建一个名为 Production.NewLocation 的表,然后使用 NEXT VALUE FOR 函数为每一行编号。
USE AdventureWorks2012 ;
GO
SELECT NEXT VALUE FOR Test.CountBy1 AS LocNumber, Name
INTO Production.NewLocation
FROM Production.Location ;
GO
SELECT * FROM Production.NewLocation ;
GO
F.授予执行 NEXT VALUE FOR 的权限
以下示例为名为 AdventureWorks\Larry 的用户授予 UPDATE 权限,以使用 Test.CounterSeq 序列执行 NEXT VALUE FOR。
GRANT UPDATE ON OBJECT::Test.CounterSeq TO [AdventureWorks\Larry] ;
请参阅
参考
CREATE SEQUENCE (Transact-SQL)