我想有一个SQL Server函数dbo.GetNextNumber()
,它将为每次调用生成序列号。据我所知,这对于本地的T-SQL函数是不可能的,因为SQL Server坚持函数必须是确定性的。但是,如果你能给我展示一个本地的T-SQL函数来做这个,我会很高兴的。
我想也许可以使用CLR函数来编写。由于CLR函数是静态的,因此需要将序列号存储在set操作的调用上下文中,因为将其存储为静态变量将导致使用相同序列的多个连接,从而导致不那么连续的数字。我对嵌入式CLR了解不够,无法查看是否可以从CLR端访问设置操作(选择,更新,删除,插入)调用上下文。
在一天结束时,以下查询
select dbo.GetNextNumber() from sysobjects
必须返回结果
1
2
3
4
5
如果需要另一个函数调用来重置上下文(如
),则可以。exec dbo.ResetSequenceNumbers()
为了防止一些误解并减少浪费时间回答错误问题的机会,请注意,我不是在寻找表的ID生成函数,并且我知道一些hack(尽管使用进程而不是函数)涉及一些具有身份列的临时表。ROW_NUMBER()
功能闭合,但也不切断。
非常感谢您的回复
凯末尔
注:令人惊讶的是,SQL Server确实有一个内置的功能。一个函数(前提是它不能在join和where子句中使用)确实很容易实现并且非常有用,但由于某些原因,它没有被包含在内。
由于您已经根据我的有关计算运行总数的文章实现了CLR序列,因此您可以使用 ROW_NUBER()
函数实现相同的目的。
ROW_NUMBER()
函数需要OVER
子句中的ORDER BY
,但是有一个很好的解决方案,如何避免由于ORDER BY
而排序。你不能把表达式放在order by中,但是你可以把SELECT aConstant
放在那里。因此,您可以使用下面的语句轻松实现数字生成。
SELECT
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNumber,
*
FROM aTable
在SQL Server的下一个版本中,您可以使用SEQUENCE来完成此操作。在早期版本中,通过插入到一个单独的"序列表"(一个只有IDENTITY列的表),然后使用SCOPE_IDENTITY()函数检索值,就可以很容易地做到这一点。您不能在函数中这样做,但可以使用存储过程。
你能给更多的信息为什么ROW_NUMBER()
不能削减它吗?在你给出的具体例子中,ROW_NUMBER()
(对OVER(ORDER BY)
进行适当的澄清)似乎当然符合你的标准。
但在某些情况下,ROW_NUMBER()
可能没有用处,在这些情况下,通常有其他技术。
也许拥有这个通用函数对你来说似乎很有用,但在大多数情况下,我发现针对手头问题量身定制的解决方案比通用函数更好,因为通用函数最终会导致更多的困难——比如你不断工作的抽象泄漏。你特别提到需要有一个重置功能。ROW_NUMBER()
不需要这样的事情,因为它有允许您指定分组的OVER(PARTITION BY ORDER BY)
。
SQL Server Denali为开发者提供了一个新的序列结构在Denali之后,在SQL Server中很容易管理和维护序列号您可以在SQL Server
中的序列号中找到详细信息。对于Denali以外的其他版本,您可以使用Sequence Tables。下面是一个SQL Server序列表的例子为了从序列表中读取序列号,您应该从这个启用了自动标识的sql表
从SQL Server 2022开始,有一个新的操作符来解决这个问题:
GENERATE_SERIES ( start, stop [, step ] )
详细信息请参见:https://learn.microsoft.com/en-us/sql/t-sql/functions/generate-series-transact-sql?view=sql-server-ver16