4

目前正在处理多租户应用程序,在存储过程中生成标识符时遇到问题。

我有一张这张表,里面有关于租户的元信息。

租户

TenantId
Name
IDPrefix,   -->Like SFT
IDStart     --> 000001

客户

TenantID
ClientIdentfier --> Like SFT000001

在存储过程中,我想生成下一个ClientIdentifierlike SFT000002

我怎样才能根据最后一个ClientIdentifier值 + 1 做到这一点?

我知道只用下面的代码取最后一个值。

select max(ClientID) + 1 from Client will give 1,2,etc

但我想我不能这样做

 DECLARE @CIdentier Varchar(50);

 select @CIdentier = select max(ClientIdentifier) + 1 from Client 
                                            to produce 'SFT000002

我怎样才能在存储过程中这样做?

编辑:

尝试了 mark_s 的答案,它就像一个魅力!

4

2 回答 2

5

这种方法在负载下是安全的,例如它不会返回任何重复项,即使大量客户端请求同时进入(这是从@remusrusanu 对 SO 上的另一个问题的回答“借用”的)。

基本上,您需要一个带有 columns 的序列表TenantIDTenantPrefix然后CurrentValue您可以使用这样的存储过程来安全地获取新值:

-- add a IDValue column to your Tenant table
ALTER TABLE dbo.Tenant
ADD IDValue INT NOT NULL DEFAULT(0)

-- create this procedure to fetch the next value for any given tenant
CREATE PROCEDURE dbo.GetNextTenantID
   @tenantID INT,    
   @NextID VARCHAR(15) OUTPUT
AS
   SET NOCOUNT ON;

   DECLARE @Out TABLE (NextVal INT, Prefix CHAR(3))

   UPDATE dbo.Tenant
   SET IDValue = IDValue + 1
   OUTPUT INSERTED.IDValue, INSERTED.IDPrefix INTO @Out(NextVal, prefix)

   SELECT TOP 1 @nextID = Prefix + CAST(NextVal AS VARCHAR(10)) FROM @Out
GO

这里的要点是:您必须在单个语句IDValue中进行递增和返回。只有使用这种方法,您才能在负载下保持安全 - 所有具有第一个、增量然后是不安全的方法并且可以返回重复项。 UPDATESELECTUPDATE

更新:不能只将这段代码包含到您的更大程序中!保持此过程不变只需从您的存储过程中调用它 - 例如:

ALTER PROCEDURE [dbo].[AddClient]  
(
   @TenantId INT,
   @FirstName NVARCHAR(100),
   @LastName NVARCHAR(100),
   @ContactPerson NVARCHAR(100)
)
AS 
BEGIN 
     SET NOCOUNT ON   

     IF @TenantId IS NULL 
        RAISERROR('The value for @TenantID should not be null', 15, 1) -- with log

     DECLARE @new_person_id INT
     DECLARE @new_patient_id INT
     DECLARE @ClientIdentifier NVARCHAR(50)

     -- call the stored procedure to get the next ClientIdentifier here
     EXEC dbo.GetNextTenantID @TenantID, @ClientIdentifier OUTPUT

     -- then go on and do your other lines of code from here on out .....
     ......
END
于 2012-12-29T09:15:59.420 回答
1

如果您有固定的前缀长度和正确的数字长度:

这是 SQLFiddle 演示

with T as 
(select 
    (isnull(max(ClientIdentfier),'SFT000000')) maxNum
from client
)

select substring(maxNum,1,3)+
       RIGHT('000000'+
             cast(cast(right(maxNum,6) as bigint)+1 as varchar(100)),
             6)
   from T

如果您需要获取已定义 TenantID 的下一个编号,例如 TenantID=2,请使用以下查询:

with T as 
(select 
    (isnull(max(ClientIdentfier),
            select top 1 IDPrefix+IDStart 
                from Tenant 
             where TenantID=2)) maxNum
from client 
     where TenantID=2
)

select substring(maxNum,1,3)+
       RIGHT('000000'+
             cast(cast(right(maxNum,6) as bigint)+1 as varchar(100)),
             6)
   from T
于 2012-12-29T08:40:04.833 回答