Sql-Server

帶條件的唯一標識符欄位

  • December 29, 2015

我有一個不在生產中的數據庫,所以主表是 CustodyDetails,這個表有一個ID int IDENTITY(1,1) PRIMARY KEY列,我正在尋找一種添加另一個唯一標識符的方法,該標識符在任何其他表中都沒有引用,我想通過考慮這個account 列的內容不會完全是身份密鑰。

這個新的身份列有一些具體的細節,這就是我的問題開始的地方。格式如下:XX/YY其中XX是一個自動遞增值,每年重置/重新啟動,YY是目前年份的最後 2 位數字SELECT RIGHT(YEAR(GETDATE()), 2)

因此,例如,假設從28/12/2015結束03/01/2016開始每天添加一條記錄,該列將如下所示:

ID    ID2     DATE_ADDED
1     1/15    2015-12-28
2     2/15    2015-12-29
3     3/15    2015-12-30
4     4/15    2015-12-31
5     1/16    2016-01-01
6     2/16    2016-01-02
7     3/16    2016-01-03

我想過用前端解析複合ID(範例中為ID2)獲取最後2位數字並與目前年份的最後2位數字進行比較,然後決定是否開始新的關聯。當然,如果能夠在數據庫端完成所有這些工作,那就太好了。

**編輯1:**順便說一句,我還看到人們使用單獨的表來儲存並行標識鍵,所以一個表標識鍵成為第二個表輔助鍵,這聽起來有點狡猾,但也許這種實現就位了?

**編輯 2:**這個額外的ID 是標記每個文件/記錄的舊文件參考。我想人們可以將其視為主 ID 的特殊別名。

該數據庫每年處理的記錄數量在過去 20 年中沒有超過 100 條,而且非常(真的,非常非常高)不可能,當然,如果它確實超過 99 條,那麼該領域將能夠繼續使用額外的數字,前端/程序將能夠超過 99,所以它不會改變事情。

當然,其中一些細節我一開始沒有提到,因為它們只會縮小解決方案的可能性以適應我的特定需求,試圖讓問題範圍更廣。

您可以使用鍵表來儲存第二個 ID 列的遞增部分。該解決方案不依賴任何客戶端程式碼,並且自動感知多年;當@DateAdded參數傳入以前未使用的年份時,它將ID2根據該年份自動開始為該列使用一組新值。如果 proc 因此用於插入前幾年的行,則這些行將插入“正確”的增量值。proc 旨在優雅地處理可能的GetNextID()死鎖,只有在嘗試更新tblIDs表時發生 5 個連續死鎖時才會將錯誤傳遞給呼叫者。

創建一個表來儲存每年包含目前使用的 ID 值的一行,以及一個儲存過程以返回要使用的新值:

CREATE TABLE [dbo].[tblIDs]
(
   IDName nvarchar(255) NOT NULL,
   LastID int NULL,
   CONSTRAINT [PK_tblIDs] PRIMARY KEY CLUSTERED 
   (
       [IDName] ASC
   ) WITH 
   (
       PAD_INDEX = OFF
       , STATISTICS_NORECOMPUTE = OFF
       , IGNORE_DUP_KEY = OFF
       , ALLOW_ROW_LOCKS = ON
       , ALLOW_PAGE_LOCKS = ON
       , FILLFACTOR = 100
   ) 
);
GO

CREATE PROCEDURE [dbo].[GetNextID](
   @IDName nvarchar(255)
)
AS
BEGIN
   /*
       Description:    Increments and returns the LastID value from
                       tblIDs for a given IDName
       Author:         Max Vernon / Mike Defehr
       Date:           2012-07-19

   */
   SET NOCOUNT ON;

   DECLARE @Retry int;
   DECLARE @EN int, @ES int, @ET int;
   SET @Retry = 5;
   DECLARE @NewID int;
   WHILE @Retry > 0
   BEGIN
       SET @NewID = NULL;
       BEGIN TRY
           UPDATE dbo.tblIDs 
           SET @NewID = LastID = LastID + 1 
           WHERE IDName = @IDName;

           IF @NewID IS NULL
           BEGIN
               SET @NewID = 1;
               INSERT INTO tblIDs (IDName, LastID) 
               VALUES (@IDName, @NewID);
           END
           SET @Retry = -2; /* no need to retry since the 
                                 operation completed */
       END TRY
       BEGIN CATCH
           IF (ERROR_NUMBER() = 1205) /* DEADLOCK */
               SET @Retry = @Retry - 1;
           ELSE
               BEGIN
               SET @Retry = -1;
               SET @EN = ERROR_NUMBER();
               SET @ES = ERROR_SEVERITY();
               SET @ET = ERROR_STATE()
               RAISERROR (@EN,@ES,@ET);
               END
       END CATCH
   END
   IF @Retry = 0 /* must have deadlock'd 5 times. */
   BEGIN
       SET @EN = 1205;
       SET @ES = 13;
       SET @ET = 1
       RAISERROR (@EN,@ES,@ET);
   END
   ELSE
       SELECT @NewID AS NewID;
END
GO

您的表,以及用於在其中插入行的 proc:

CREATE TABLE dbo.Cond
(
   CondID INT NOT NULL
       CONSTRAINT PK_Cond
       PRIMARY KEY CLUSTERED
       IDENTITY(1,1)
   , CondID2 VARCHAR(30) NOT NULL
   , Date_Added DATE NOT NULL
);

GO
CREATE PROCEDURE dbo.InsertCond
(
   @DateAdded DATE
)
AS
BEGIN
   DECLARE @NextID INT;
   DECLARE @Year INT;
   DECLARE @IDName NVARCHAR(255);
   SET @Year = DATEPART(YEAR, @DateAdded);
   DECLARE @Res TABLE
   (
       NextID INT NOT NULL
   );
   SET @IDName = 'Cond_' + CONVERT(VARCHAR(30), @Year, 0);
   INSERT INTO @Res (NextID)
   EXEC dbo.GetNextID @IDName;

   INSERT INTO dbo.Cond (CondID2, Date_Added)
   SELECT CONVERT(VARCHAR(30), NextID) + '/' + 
       SUBSTRING(CONVERT(VARCHAR(30), @Year), 3, 2), @DateAdded
   FROM @Res;
END
GO

插入一些範例數據:

EXEC dbo.InsertCond @DateAdded = '2015-12-30';
EXEC dbo.InsertCond @DateAdded = '2015-12-31';
EXEC dbo.InsertCond @DateAdded = '2016-01-01';
EXEC dbo.InsertCond @DateAdded = '2016-01-02';

顯示兩個表:

SELECT *
FROM dbo.Cond;

SELECT *
FROM dbo.tblIDs;

結果:

在此處輸入圖像描述

密鑰表和儲存過程來自這個問題。

引用自:https://dba.stackexchange.com/questions/124798