2011-08-17 43 views
1

我希望有一个SQL Server函数dbo.GetNextNumber(),它可以为每个调用生成序号。据我所知,使用本地T-SQL函数是不可能的,因为SQL Server坚持认为函数必须是确定性的。但是,如果你能向我展示一个原生T-SQL函数,那么这真的会让我有一天的时间。用于生成连续号码的SQL Server函数

我想也许这可能是使用CLR函数编写的。由于CLR函数是静态的,因此序列号需要存储在set操作的调用上下文中,因为将其存储为静态变量会导致使用相同序列的多个连接,从而导致不那么连续的数字。我不太了解嵌入式CLR,以了解是否可以从CLR端访问set operation(select,update,delete,insert)调用上下文。

在一天结束的时候,下面的查询

select dbo.GetNextNumber() from sysobjects 

必须返回结果

1 
2 
3 
4 
5 

这是确定的,如果另一个函数调用来重置上下文是必要像

exec dbo.ResetSequenceNumbers() 

为了避免一些误解,并减少浪费你的时间回答错误的任务离子,请注意,我没有寻找一个表的ID生成函数,我知道一些黑客(尽管使用proc而不是函数),涉及一些具有标识列的临时表。 ROW_NUMBER()函数接近,但它也不会削减。

非常感谢任何反应

末尔

附:令人惊讶的是,SQL Server确实有一个内置的功能。一个函数(假设它不能在连接和where子句中使用)很容易实现,并且非常有用,但由于某种原因,它不包含在内。

+7

而不是问一个“sql服务器函数dbo.GetNextNumber()”,告诉我们你正在尝试解决的问题。 –

+1

您可以使用只有一个“ID INT IDENTITY(1,1)”列的“助手”表,并在每个INSERT后使用“SELECT SCOPE_IDENTITY()”来获取值,或者等待SQL Server“Denali “(2011/2012),它将[SEQUENCES as native database objects](http://sqlblog.com/blogs/aaron_bertrand/archive/2010/11/11/sql-server-11-denali-using-sequence.aspx )正是为了这个目的 –

+1

SQL-Server函数不必是确定性的。在某些情况下,需要确定性函数(例如计算列)。 –

回答

5

插入伪记录如您根据我的文章有关运行总计的计算实现的CLR序列,您可以使用ROW_NUBER()函数实现相同的功能。

ROW_NUMBER()功能需要OVER子句中的ORDER BY,但有一个很好的解决办法如何避免排序由于ORDER BY。您不能按顺序放置表达式,但您可以在此放置SELECT aConstant。所以你可以使用下面的语句轻松实现数字生成。

SELECT 
    ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNumber, 
    * 
FROM aTable 
+0

哇,真的很好的黑客。谢谢 –

2

在SQL Server的下一个版本中,您可以使用SEQUENCE来执行此操作。在早期版本中,通过插入到单独的“序列表”(仅包含IDENTITY列的表)中,然后使用SCOPE_IDENTITY()函数检索值很容易。你不能在一个函数中做到这一点,但你可以使用存储过程。

+0

这不会做,因为sql server不允许在一个函数中封装这个逻辑。也许,我应该创建一个CLR函数来做到这一点。但这将是一个黑客,而不是一个优雅的解决方案 –

+0

我想每个人都想知道的是,为什么在一个函数而不是程序中这么做对你来说如此重要。您正试图将功能用于他们无意使用的功能。 – sqlvogel

2

您能否提供更多关于为什么ROW_NUMBER()不能削减的信息?在你给出的具体例子中,ROW_NUMBER()(对OVER(ORDER BY)进行适当的说明)肯定似乎符合你的标准。

但是肯定有些情况下ROW_NUMBER()可能没有用,在这些情况下,通常还有其他技术。

也许有这个一般功能对你来说似乎很有用,但是在大多数情况下,我发现针对手头问题定制更好的解决方案比通用功能更好,最终导致更多的困难 - 比如泄漏抽象你正在不断努力。您特别提到需要具有重置功能。 ROW_NUMBER()不需要这样的东西,因为它具有允许您指定分组的OVER(PARTITION BY ORDER BY)

+0

row_number需要一个over谓词,它强制你指定一个order by子句。在我的一些情况下,我需要一个自然顺序非常重要的临时表。而且,在其他一些情况下,可以在那里指定的列在运行时才会知道,这迫使您使用动态SQL。最后,您必须将所有内容都包含到子查询中才能使用row_number()的值。不太好 –

+2

@Kemal埃尔多安没有这样的事情在SQL中的自然顺序。如果您依赖插入订单或聚集索引或其他任何内容,没有ORDER BY,则不会保证订单。虽然您可能碰巧得到一份订单并且看起来可靠,但没有ORDER BY就没有保证。 SQL是一种声明性语言,没有声明或您的期望,没有保证。 –

+0

在sql理论中确实没有像自然顺序那样的东西。但是为堆表实现插入操作最简单也是最自然的方式就是保持插入顺序不变。这就是为什么微软永远不会改变这一点,我没有理由改变它。因此,在实践中,存在自然顺序的东西 –

0

的SQL Server Denali车型为开发人员 一个新的序列结构,它易于管理和维护SQL Server中的序列号迪纳利 后,您可以在Sequence Numbers in SQL Server

细节对其它版本比德纳里,你可以使用序列表。 这里是Sequence Table in SQL Server 一个样品从序列表中读取序列号,你应该从这个自动标识启用SQL表