Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server存储过程中的自定义标识符生成_Sql_Sql Server_Sql Server 2008_Stored Procedures - Fatal编程技术网

SQL Server存储过程中的自定义标识符生成

SQL Server存储过程中的自定义标识符生成,sql,sql-server,sql-server-2008,stored-procedures,Sql,Sql Server,Sql Server 2008,Stored Procedures,当前正在处理多租户应用程序,在存储过程中生成标识符时遇到问题 我在这个表中有一个关于租户的元信息 租户 TenantId Name IDPrefix, -->Like SFT IDStart --> 000001 TenantID ClientIdentfier --> Like SFT000001 客户端 TenantId Name IDPrefix, -->Like SFT IDStart --> 000001 TenantID C

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

我在这个表中有一个关于租户的元信息

租户

TenantId
Name
IDPrefix,   -->Like SFT
IDStart     --> 000001
TenantID
ClientIdentfier --> Like SFT000001
客户端

TenantId
Name
IDPrefix,   -->Like SFT
IDStart     --> 000001
TenantID
ClientIdentfier --> Like SFT000001
在存储过程中,我想生成下一个
ClientIdentifier
,比如
SFT000002

如何基于上一个
ClientIdentifier
value+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
我如何在存储过程中这样做

编辑:


试过马克的答案,效果很好

如果前缀长度和右位长度固定:

如果需要获取定义的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

这种方法在负载下是安全的,例如,即使大量客户端请求同时出现,它也不会返回任何副本(这是从@remusrusanu对另一个问题的回答中“借用的”)

基本上,您需要一个包含列
TenantID
TenantPrefix
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
,并在单个
语句中返回它。只有使用此方法,您才能在负载下安全-所有具有
先选择
、递增,然后更新
的方法都是不安全的,并且可以返回重复的

更新:您不能将这段代码包含到您的更大过程中!将此过程保持原样,只需从存储过程中调用它—类似于:

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

以前有人问过我关于SO…@MitchWheat的问题,我能得到那个SO链接吗?我搜索失败。加载时,
SELECT MAX(ClientID)+1
方法从来都不安全-您将获得重复项。使用标识(1,1),如果您需要生成类似SFTxxxxxx的ID,您可以从ID生成,并且可以保留重复项away@marc_s谢谢你的提示。但是有没有一个好方法可以在负载下完成这项工作呢?该应用程序将被许多租户使用,因此如果您添加更多的要点,它将非常有用,看起来很棒。但是,每个租户可能都有自己的标识符和起始编号。示例租户2可能具有“TET”和起始编号“20569”。有没有办法读取这些数据并生成下一个数字?我添加了一个查询,以获取定义的租户的下一个数字。我走这条路!我是否可以将此GetNextEnablenId设为函数并在存储过程中使用?@user1909604:不,您不能-函数不能修改database@user1909604:如果您尝试将其转换为函数,您将得到如下错误:
Msg 443,级别16,状态15,过程。。。。。。,第7行/在函数中使用副作用运算符“UPDATE”无效。
我在过程本身中尝试了相同的操作,但出现了一些新错误!。用我的问题更新了。请帮我修一下。