2011-08-17 26 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表