【问题标题】:Generate a unique column sequence value based on a query handling concurrency基于查询处理并发生成唯一的列序列值
【发布时间】:2021-08-09 04:08:59
【问题描述】:

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

唯一值的模板是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;

【问题讨论】:

  • 创建一个视图,其中包含一个具有窗口函数的新列。

标签: sql sql-server


【解决方案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, xact_abort 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;

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这种方式仍然可以得到重复。
    猜你喜欢
    • 2016-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多