2017-08-02 55 views
0

我正在使用下面的T-SQL創建一個計算列的表,其中給出了我在'BID(The Year)-0000'中的ID。問題是我想在年份發生變化時重置ID中的一系列零。例如,表中的最後一個ID是BID2017-0923,當年更改時我希望將該系列重置爲例如'BID2018-0001'如何更改計算列中的零系列

這是當前我正在使用的T-SQL。

CREATE TABLE Books 
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    IDCreateDate DATETIME NOT NULL DEFAULT GETDATE(), 
    BookID AS ('BID' + LTRIM(YEAR(IDCreateDate)) + '-' + RIGHT('0000' + LTRIM(ID), 4)), 
    ISBN VARCHAR(32), 
    BookName NVARCHAR(50), 
    AuthorName NVARCHAR(50), 
    BLanguage VARCHAR(50), 
    StaId int, 
    StuId int, 
    CatNo int 
); 

UPDATE: 此外,我想ID山坳基礎上,今年記住上次ID它has.For例如,在列的最後一個id爲BID2017-0920當我改變的一年2010 ,它必須重置數字系列,例如BID2010-0001,但是當我將年份切換回2017年時,我不希望系列重置,而是希望它從BID2017-0921開始。

+0

您可能需要在插入行時使用觸發器來執行此操作。 –

+0

創建表格時不可以這樣做嗎? –

+1

您的主鍵中不能有重複的值,這實際上就是您要求的。當你在某一年超過9,999個值時,你會怎麼做? –

回答

0

編輯#1:我根據最新OP的評論

更新我的解決方案
/* 
CREATE TABLE dbo.CustomSequence (
    Name VARCHAR(50) NOT NULL, 
    Prefix  VARCHAR(10) NOT NULL, 
    LastValue VARCHAR(50) NULL, -- All generated values will have following pattern: PrefixYYYY-SeqvNumber 
    LastYear SMALLINT NOT NULL, 
     CONSTRAINT PK_CustomSequence_Name_LastYear PRIMARY KEY (Name, LastYear), 
    LastNumber SMALLINT NULL 
); 
GO 
-- Config OrderSequence 2014 
INSERT dbo.CustomSequence (Name, Prefix, LastValue, LastYear, LastNumber) 
VALUES ('BookSequence', 'BID', NULL, 2014, 1) 
GO 
-- Config OrderSequence 2017 
INSERT dbo.CustomSequence (Name, Prefix, LastValue, LastYear, LastNumber) 
VALUES ('BookSequence', 'BID', NULL, 2017, 1) 
GO 
*/ 

-- Generating new seq 
    -- IN Parameters 
    DECLARE @CustomSequenceName VARCHAR(50) = 'BookSequence' 
    DECLARE @Year    SMALLINT = 2017 --YEAR(GETDATE()) 
    DECLARE @LenOfNumber  TINYINT = 4 
    -- End of IN Parameters 
    -- OUT Parameters 
    DECLARE @GeneratedValue  VARCHAR(50) 
    -- End of OUT Parameters 

    UPDATE s 
    SET  LastNumber  = IIF(LastValue IS NULL, LastNumber, LastNumber + 1) + IIF(LastNumber = REPLICATE('9', @LenOfNumber), 1/0, 0), 
      @GeneratedValue = LastValue = Prefix + LTRIM(@Year) + '-' + RIGHT(REPLICATE('0', @LenOfNumber) + LTRIM(IIF(LastValue IS NULL, LastNumber, LastNumber + 1)), @LenOfNumber) 
    FROM dbo.CustomSequence s 
    WHERE s.Name = @CustomSequenceName 
    AND  s.LastYear = @Year 
-- End of Generating new seq 

SELECT @GeneratedValue 
SELECT * FROM dbo.CustomSequence 
--> BID2017-0001, BID2017-0002, BID2017-0003, ... 

注1:這與悲觀併發控制(SQL Server數據庫引擎的默認行爲)

解決工作

注2:如果我們在下面的代碼段達到10000

... IIF(LastNumber = 9999, 1/0, 0) ... 

將引發異常

Msg 8134, Level 16, State 1, Line 30 
Divide by zero error encountered. 
The statement has been terminated. 

注3:UPDATE語句可以被封裝到與@CustomSequenceName VARCHAR(50)作爲輸入參數和@GeneratedValue VARCHAR(50) OUTPUT作爲OUT [PUT]參數的存儲過程。

注#4:@LenOfNumber允許定製序列號的長度(默認值爲4)

編輯#2:

UPDATE語句可以用下面的INSERT + UPDATE語句的組合取代:

SET XACT_ABORT ON 
BEGIN TRAN 
    IF NOT EXISTS(SELECT * FROM dbo.CustomSequence s WITH(HOLDLOCK) WHERE s.Name = @CustomSequenceName AND s.LastYear = @Year) 
    BEGIN 
     INSERT dbo.CustomSequence (Name, Prefix, LastValue, LastYear, LastNumber) 
     VALUES (@CustomSequenceName, @Prefix, NULL, @Year, 1) 
    END 
    UPDATE s 
    SET  LastNumber  = IIF(LastValue IS NULL, LastNumber, LastNumber + 1) + IIF(LastNumber = REPLICATE('9', @LenOfNumber), 1/0, 0), 
      @GeneratedValue = LastValue = Prefix + LTRIM(@Year) + '-' + RIGHT(REPLICATE('0', @LenOfNumber) + LTRIM(IIF(LastValue IS NULL, LastNumber, LastNumber + 1)), @LenOfNumber) 
    FROM dbo.CustomSequence s WITH(HOLDLOCK) 
    WHERE s.Name = @CustomSequenceName 
    AND  s.LastYear = @Year 
COMMIT