2017-08-02 16 views
0

私は'BID(The Year)-0000'にIDを与える計算列を持つテーブルを作成するために、以下のT-SQLを使用しています。問題は、年が変更されたときに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:さらに 、私は私が2010年に年を変更するとき、それはhas.For例、列の最後のidがBID2017-0920であるために年に基づいて、その最後のIDを記憶していたID COLを希望しますたとえば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ステートメントは、OUT [PUT]パラメータとして入力パラメータとして@CustomSequenceName VARCHAR(50)@GeneratedValue VARCHAR(50) OUTPUTしてストアドプロシージャにカプセル化することができます。

#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 
関連する問題