4

現在マルチテナントアプリケーションで作業していますが、ストアドプロシージャで識別子を生成する際に問題があります。

テナントに関するメタ情報を含むこのテーブルがあります。

テナント

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

クライアント

TenantID
ClientIdentfier --> Like SFT000001

ClientIdentifierストアドプロシージャで、次のようなを生成したいと思い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に関する別の質問に「借用」されます)。

基本的に、列TenantIDを含むシーケンステーブルが必要です。次に、次のようなストアドプロシージャを使用して、新しい値を安全にフェッチできます。TenantPrefixCurrentValue

-- 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 に答える