2011-08-03 48 views
0

我有一個存儲發票的SQL Server表讓我們稱之爲發票。我需要實現發票的連續自動編號功能(不是不連續的自動功能)。此外,我應該注意併發問題,例如用戶A和用戶B同時開具發票,但兩張發票不應該有相同的數字(顯然)。連續自動編號

什麼是T-SQL中理想的實現方法?

+0

如果我不必使用標識列? – Ioannis

+0

我的理解是,SQL Server IDENTITY列是按照它們的方式實現的,這是因爲兩個或多或少同等重要的問題:併發性和性能。由於前者,你保證有獨特的價值,但你必須忍受可能的差距,因爲後者。現在你正試圖消除差距的可能性(在你自己的IDENTITY實現中)。你認爲你會遭受什麼樣的回報? –

+0

我並不十分清楚......例如,最後一張發票的編號爲190,我刪除了發票#32。然後,新插入的發票將需要數字32.這就是我不需要身份的原因。 – Ioannis

回答

2

我們做了類似的一種方式是創建一個名爲useID的表,其中只有一列名爲[ID]。我們使用Integer數據類型。該表也只有一行。更多關於這一點。

現在,每次我們需要記錄事件時,我們都會從useID開始SELECT,然後運行我們的交易,並將此[ID]值用於跟蹤目的。在我們有SELECT編輯[ID]之後,我們將useID中的值增加1(或者我們需要的系統)。通過這種方式,我們保持獨特和連續的值。我們可以從[ID]值的目標中刪除,而不會影響新值[ID]的順序。這樣的表現非常好,因爲我們每晚使用這種方式進行約1000萬筆交易,並且我們每3個月左右重置一次起始價值,因爲我們沒有將這些項目保留很長時間。

2

一個IDENTITY列。

如果您需要一個字母數字的發票號碼,我建議您使用所需的格式更新您的問題。

如果您刪除記錄,在INSERT過程中遇到錯誤,將包含INSERT的事務回滾到表中,或者種子由相關的dbcc命令更新,則只會存在間隙。

如果你真的需要重新使用差距(而且我確實不會這樣做,比如發票,例如,在你的例子中,發票#32會有更晚的日期,然後發票#190 ......):那麼你在可序列化的事務中,可以找到最低的空閒值,設置標識插入,插入具有該Id值的行,然後設置標識插入並提交事務。

像這樣(未經):

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 

BEGIN TRAN 
SET IDENTITY_INSERT dbo.myTable ON 

DECLARE @minId int = -1 

;WITH cterows(Id, rownum) 
AS 
(
    SELECT Id, row_number() OVER(ORDER BY Id ASC) AS rownum 
) 
SELECT @minId = MIN(rownum) FROM cterows 
WHERE Id <> rownum 

IF (@minId IS NOT NULL AND @minId <> -1) 
    BEGIN 
    -- found a gap 
    -- Insert at @minId 
    END 
ELSE 
    BEGIN 
    -- No gap, INSERT as normal 
    END 


SET IDENTITY_INSERT dbo.myTable OFF; 
COMMIT 
1

如果不是必要的,這些數字要繼續,你可以創建隨機數,但如果要繼續則可以使該列IDENTITY colunm

檢查這個post來創建隨機數

0

,您可以撥打SQL Varchar列字母數字發票號,在這裏,你需要不生成唯一的發票或者可以使用IDENTITY列。