我正在创建一个母公司表与客户表的客户表。指示(恼怒)我将为客户表创建一个主键,该键是公司ID的组合,该公司ID是客户表中现有的varchar(4)列,例如customer.company
其余的varchar(9)主键应为零填充计数器,该计数器将根据该公司内的客户数量递增。
例如,如果company = MSFT且这是MSFT记录的第一条插入:PK在随后的插入中应为MSFT00001,PK将为MSFT00001,MSFT00002等。然后,当company = INTL并插入其第一条记录时,第一条记录将为INTL00001
我从其他stackoverflow响应创建的而不是触发器和udf开始。
ALTER FUNCTION [dbo].[GetNextID] ( @in varchar(9) ) RETURNS varchar(9) AS BEGIN DECLARE @prefix varchar(9); DECLARE @res varchar(9); DECLARE @pad varchar(9); DECLARE @num int; DECLARE @start int; if LEN(@in)<9 begin set @in = Left(@in + replicate('0',9) , 9) end SET @start = PATINDEX('%[0-9]%',@in); SET @prefix = LEFT(@in, @start - 1 ); declare @tmp int; set @tmp = len(@in) declare @tmpvarchar varchar(9); set @tmpvarchar = RIGHT( @in, LEN(@in) - @start + 1 ) SET @num = CAST( RIGHT( @in, LEN(@in) - @start + 1 ) AS int ) + 1 SET @pad = REPLICATE( '0', 9 - LEN(@prefix) - CEILING(LOG(@num)/LOG(10)) ); SET @res = @prefix + @pad + CAST( @num AS varchar); RETURN @res END
我将如何编写触发器而不是触发器来插入值并递增此主键。还是应该放弃并开始割草业务?
很抱歉,tmpvarchar变量SQL Server在没有它的情况下给了我奇怪的结果。
我同意反对者的观点,但“接受不能改变的原则”倾向于降低总体压力水平,恕我直言。请尝试以下方法。
缺点
从好的方面来看,这种方法没有任何竞争条件,并且它并不是太骇人听闻的破解方法,以至于不能真正地冒犯我的感觉。所以…
首先,从密钥生成表开始。每个公司将包含1行,其中包含您的公司标识符和一个整数计数器,每次执行插入操作时我们都会增加该计数器。
create table dbo.CustomerNumberGenerator ( company varchar(8) not null , curr_value int not null default(1) , constraint CustomerNumberGenerator_PK primary key clustered ( company ) , )
其次,您将需要一个这样的存储过程(实际上,您可能希望将此逻辑集成到负责插入客户记录的存储过程中。此存储过程接受公司标识符(例如“ MSFT”)作为其唯一参数。此存储过程执行以下操作:
SELECT
干得好:
create procedure dbo.GetNewCustomerNumber @company varchar(8) as set nocount on set ansi_nulls on set concat_null_yields_null on set xact_abort on declare @customer_number varchar(32) -- -- put the supplied key in canonical form -- set @company = ltrim(rtrim(upper(@company))) -- -- if the name isn't already defined in the table, define it. -- insert dbo.CustomerNumberGenerator ( company ) select id = @company where not exists ( select * from dbo.CustomerNumberGenerator where company = @company ) -- -- now, an interlocked update to get the current value and increment the table -- update CustomerNumberGenerator set @customer_number = company + right( '00000000' + convert(varchar,curr_value) , 8 ) , curr_value = curr_value + 1 where company = @company -- -- return the new unique value to the caller -- select customer_number = @customer_number return 0 go
您可能要将其集成到将行插入到customer表中的存储过程中的原因是,它使得将它们全部聚集到一个事务中;否则,当插入失败时,您的客户数量可能/将出现缺口。