根据查询处理并发生成唯一的列序列值

时间:2019-10-10 19:16:17

标签: sql sql-server

我需要根据另一个查询的结果自动生成列的值。因为此列值必须是唯一的,所以我需要考虑并发请求。该查询需要为支持凭单生成器生成一个唯一值。

唯一值的模板是CustomerName-Month-Year-SupportTicketForThisMonthCount

因此脚本应自动生成:

  • AcmeCo-10-2019-1
  • AcmeCo-10-2019-2
  • AcmeCo-10-2019-3

,以此类推。如果同时为AcmeCo创建了两个支持凭单,如何确保AcmeCo-10-2019-1不会生成两次?

insert into SupportTickets (name)
  select concat_ws('-', @CustomerName, @Month, @Year, COUNT())
  from SupportTickets
  where customerName = @CustomerName
  and CreatedDate between @MonthStart and @MonthEnd;

2 个答案:

答案 0 :(得分:1)

一种可能性:

创建计数器表:

create table Counter (
   Id int identify(1,1),
   Name varchar(64)
   Count1 int
)

名称是序列的唯一标识符,在您的情况下,名称为CustomerName-Month-Year,即,对于每个“客户/年/月/月”组合,您都将在此表中以一行结尾。

然后编写类似于以下内容的存储过程以分配新的序列号:

CREATE PROCEDURE [dbo].[Counter_Next]
(
  @Name varchar(64)
  , @Value int out -- Value to be used
)
AS
BEGIN
  set nocount on;

  declare @Temp int;

  begin tran
    -- Ensure we have an exclusive lock before changing variables
    select top 1 1 from dbo.Counter with (tablockx);

    set @Value = null; -- if a value is passed in it stuffs us up, so null it

    -- Attempt an update and assignment in a single statement
    update dbo.[Counter] set
      @Value = Count1 = Count1 + 1
    where [Name] = @Name;

    if @@rowcount = 0 begin
      set @Value = 10001; -- Some starting value
      -- Create a new record if none exists
      insert into dbo.[Counter] ([Name], Count1)
        select @Name, @Value;
    end
  commit tran

  return 0;
END

答案 1 :(得分:0)

您可以考虑使用TIME类型而不是COUNT()创建唯一值。这样一来,重复的可能性就大大降低了。希望有帮助