Sql-Server

使用 SQL Server 自定義序列

  • October 19, 2017

使用 SQL Server 生成自定義自動生成序列的最佳方法是什麼?

這是我的要求:

  • 我的應用程序託管在 10 個不相互連接的獨立伺服器上。
  • 每個實例都應生成一個序列號,所有這些數據將使用 SQL Server 的合併複製合併到所有數據庫中。
  • 生成的序列在所有伺服器中應該是唯一的。

為了實現這一點,我創建了一個函式來為序列號添加一個伺服器 ID,並將其用作計算列。但是當我添加數據時,我得到了以下異常:

“超出最大儲存過程、函式、觸發器或視圖嵌套級別(限制 32)。”

這是我的桌子和功能。請提出更好的方法。

create table Customers
(
   CID int identity not null primary key,
   CustomerName varchar(50)
)

ALTER function [dbo].[NextCustomerNumber]()
returns bigint
as
begin
   declare @lastval bigint
   declare @serverId int
   declare @newval bigint
   set @lastval = (select max(CustomerNumber) from Customers)
   set @serverId= 1 -- Server ID pulls from some settings
   set @newval=CONVERT(bigint, (CAST(@serverId as varchar(2))+CONVERT( varchar(10),(RIGHT(@lastval,(LEN(@lastval)-LEN(@serverId)))+1))))
   return @newval

end

Alter table Customers add CustomerNumber as dbo.NextCustomerNumber()

為什麼不直接使用SEQUENCE2012 年引入 SQL Server 的實際值?

以下方法重載了BIGINT值,其中前 10 位數字表示轉換為 a 後的伺服器 IP 地址BIGINT(通過 SQLDenis 在此部落格文章中概述的方法),最右邊的 10 位數字表示實例本地的 CustomerID。ABIGINT最多可以有 19 位數字,但是因為最左邊的數字永遠不會高於4開始序列,這允許的客戶數量比允許的最大值要多得多INT(程式碼中的註釋在 a更多細節)。

這種方法的唯一要求是該解決方案最多只能部署到每台伺服器一個實例(因為 IP 在同一伺服器上託管的實例之間不會是唯一的)。如上所述,這種方法仍然允許INT您的解決方案中每個實例最多有 2,147,483,647 個客戶。因為CID表中的列在您的問題中被定義為 a INT,所以我假設這是可以接受的。它仍然與您在其他任何地方找到的一樣快。

-- This sequence will have a dynamic starting number **PER SERVER** based on IP
-- Max value for BigINT is 9,223,372,036,854,775,807
-- Max value for INT is                2,147,483,647
-- Max IP (255.255.255.255) to BIGINT: 4,294,967,295
-- IP to padded BIGINT:    4,294,967,295
--                       *             1,000,000,000
--                       ---------------------------
-- Max Starting Value =    4,294,967,295,000,000,000

-- Variables to capture server id (IP) and generate sequence DDL statement
DECLARE @serverid BIGINT, @sequenceDSQL VARCHAR(4000)

-- Convert IP to BIGINT
SELECT TOP(1) @serverid =
       (CONVERT(bigint, PARSENAME(local_net_address,1)) +
        CONVERT(bigint, PARSENAME(local_net_address,2)) * 256 +
        CONVERT(bigint, PARSENAME(local_net_address,3)) * 65536 +
        CONVERT(bigint, PARSENAME(local_net_address,4)) * 16777216)
FROM sys.dm_exec_connections AS c
WHERE c.local_net_address IS NOT NULL;

-- Shift Server IP value to left of the BIGINT value
SET @serverid = @serverid * 1000000000

-- Generate Dynamic SQL DDL for CREATE SEQUENCE Statement
SET @sequenceDSQL = '
CREATE SEQUENCE dbo.NextCustomerNumber
AS BIGINT
   START WITH ' + CAST(@serverid AS VARCHAR(19)) + '
   INCREMENT BY 1
   NO MAXVALUE
   NO CACHE -- Or switch to CACHE if you''re seeing performance issues on inserts'

-- Create the Sequence
EXEC(@sequenceDSQL)

-- Create the Table
create table dbo.Customers
(
   CID int identity not null primary key,
   CustomerName varchar(50),
   CustomerNumber bigint DEFAULT (NEXT VALUE FOR dbo.NextCustomerNumber)
)
GO

如果您還想考慮該@serverid值的埠號,您將達到 aBIGINT可以容納的限制,因此我建議您為伺服器提供一些其他唯一標識符,而不是 IP/埠。但是,我的程式碼應該顯示一種通用方法,您可以根據需要進行調整以解決您的問題。

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