生成唯一的批次ID(SQL Server)

时间:2018-07-09 15:39:49

标签: sql sql-server tsql

这可能是1x中的2x问题。抱歉,但是去了:

问题

每次用户将一些数据上传到SQL Server时,我都会创建一个唯一的批处理ID。目前,我是通过查看“身份规范”的最后一个值并为其添加+1来实现的。

出现问题,就像您可能已经猜到的那样,如果多个用户同时输入数据,他们俩将获得相同的批次ID ...

可能的解决方案

为了减轻这个问题,我想出了这种方法来生成3个字母+随机数;和(最后一个ID值+ 1):

DECLARE @tmp CHAR(3) = CHAR(CAST(RAND()*26 AS int)+65) + CHAR(CAST(RAND()*26 AS int)+65) + CHAR(CAST(RAND()*26 AS int)+65);
SELECT @tmp;

select cast(RAND()*9999 as int)

(1)我不确定如何将其连接为一行字符串。

(2)另一个问题是,有没有办法100%保证每个用户每次提交请求时都获得唯一的批次ID,而不论有多少人同时执行请求? / p>

非常感谢您对此的投入。

6 个答案:

答案 0 :(得分:2)

您需要一个带有Bigint Identity列的“上传”表作为BatchID,然后为每次用户上传添加新行。

服务器将保持正确的值并防止冲突。

答案 1 :(得分:2)

我将为此使用内置函数:

select newid()
> 240CA878-135E-4176-AE57-0FA83FF74037

答案 2 :(得分:1)

对于第一个问题,您可以为随机数创建一个变量,将其作为char(4)并将其简单地连接为2,或者将其创建为int,然后在连接时将其转换为VARCHAR。 所有串联在一起的字符串都必须是字符串。

DECLARE @tmp CHAR(3) = CHAR(CAST(RAND()*26 AS int)+65) + CHAR(CAST(RAND()*26 AS int)+65) + CHAR(CAST(RAND()*26 AS int)+65);
SELECT @tmp;

DECLARE @randNum VARCHAR(4) = CAST(RAND()*9999 AS INT)
-- OR DECLARE @randNum INT = CAST(Rand()*9999) AS INT)
SELECT @randNum

DECLARE @batchID VARCHAR(MAX) = @tmp + @randNum
-- OR DECLARE @batchID VARCHAR(MAX) = @tmp + CAST(@randNum AS VARCHAR)
SELECT @batchID

答案 3 :(得分:1)

尝试以下操作:

1)

DECLARE @tmp CHAR(7) = CHAR(CAST(RAND()*26 AS int)+65) + CHAR(CAST(RAND()*26 AS int)+65) + CHAR(CAST(RAND()*26 AS int)+65) + cast(cast(RAND()*9999 as int) as varchar(4));
SELECT @tmp;

2)是的,我是这样。

答案 4 :(得分:1)

1-串联部分非常简单,您可以执行以下操作:

DECLARE @tmp VARCHAR(10); 

SET @tmp = CHAR(CAST(RAND()*26 AS int)+65) 
         + CHAR(CAST(RAND()*26 AS int)+65) 
         + CHAR(CAST(RAND()*26 AS int)+65)
         + CAST(cast(RAND()*9999 as int) AS VARCHAR(4));

SELECT @tmp;

2-我建议您在表中填充要发布给用户的随机值,然后从中进行选择,以避免出现竞争情况。

用两个列BatchNumbersBatchNumber创建一个名为Used的表。

填充批次号表,并将0作为“已用列”的默认值。

然后,每次需要批号时,请执行以下操作。

CREATE PROC dbo.usp_Get_BatchNumber
  @BatchNumber VARCHAR(10) OUTPUT
AS
BEGIN
  SET NOCOUNT ON;

Declare @t TABLE (BN VARCHAR(10));

    UPDATE TOP (1) BatchNumbers
     SET Used = 1 
    OUTPUT inserted.BatchNumber INTO @t (BN )
    WHERE Used = 0; 

    SELECT @BatchNumber = BN FROM @t;

END

答案 5 :(得分:1)

我赞成特里·卡门(Terry Carmen)的回答,但从他的评论看来,他的建议与我最初的想法有所出入,因此这里有一个完整的例子。我认为您想要一个表,该表具有一个用IDENTITY属性定义的键,该键将告诉SQL Server您想要该列中的唯一顺序值,并且希望数据库担心保证它的详细信息。这样。

create table dbo.Import
(
    -- identity(1, 1) means that SQL Server will automatically assign values for
    -- this column when you insert a record, with 1 being the first value 
    -- assigned and each subsequent value incrementing by 1.
    Identifier bigint not null identity(1, 1),

    -- This column for illustration only; replace it with whatever data you need
    -- to store.
    YourStuffHere varchar(max)
);

-- Now simply use any INSERT or MERGE command against dbo.Import, and omit the
-- Identifier column from the list of columns whose values the command supplies.
-- Then you can use the SCOPE_IDENTITY() function or an OUTPUT clause to capture
-- the Identifier value that SQL Server has inserted.

-- Example 1: INSERT with explicit values and OUTPUT.
insert dbo.Import 
    (YourStuffHere) 
output
    inserted.Identifier
values
    ('Example 1');

-- Example 2: INSERT/SELECT with OUTPUT.
insert dbo.Import
    (YourStuffHere)
output
    inserted.Identifier
select
    'Example 2';

-- Example 3: INSERT with SCOPE_IDENTITY().
insert dbo.Import
    (YourStuffHere)
values
    ('Example 3');
select Identifier = convert(bigint, scope_identity());

-- Show table contents.
select * from dbo.Import;

上面的第一条INSERT语句产生以下结果:

Identifier
1

第二个:

Identifier
2

第三个SELECT之后的INPUT给出:

Identifier
3

最后的SELECT向您显示表的内容:

Identifier   YourStuffHere
1            Example 1
2            Example 2
3            Example 3

这是解决此问题的最简单方法,因为它允许SQL Server为您完成所有实际工作。如果我误解了您的要求,请告诉我。