使用SQL创建唯一标识符

3
有没有一些SQL编码可以在点击获取默认按钮时生成唯一标识符?我正在寻找一种在将纸质文件放入存储之前为其编号的系统。问题是有3个办事处,每个办事处都需要一个连续编号系统(即P001、P002、P003和C001、C002...)。
以下是我目前用于生成唯一标识号前缀的代码。 SELECT CASE WHEN ptBranch=3 THEN 'P' WHEN ptBranch=4 THEN 'A' ELSE 'C' END + CONVERT(VARCHAR(2),GETDATE(),12) FROM LAMatter WHERE ptMatter = $Matter$ 这个想法是,该代码可以生成整个文件编号,例如P110001、P110002(其中P、C或A表示文件所在的办事处,11表示文件被放入存储的年份)。
非常感谢任何指导。

1
“sequential” 方面有多重要?插入失败后是否可能留下任何间隙? - Martin Smith
不幸的是,这非常重要——因为它使得在存储中找到缺失的文件变得更加容易(在归档后,它们一直被放进和取出)——显然,如果数字中有间隙,你就无法知道是否缺少了一个文件或者数字未被分配。 - James Parish
好的,这完全排除了“identity”的可能性,因为它根本不能保证这一点(即使您有3个不同的表,仍然可能从已回滚的事务中获得间隙)。 - Martin Smith
我刚注意到你说你想在点击“获取默认按钮”时生成一个新的“唯一标识符” - 这是否意味着在插入任何数据之前就生成了该数字(例如打印标签或其他东西)?如果是这样,如果生成了一个数字但从未使用过会发生什么?此外,多个人是否会处理这些文件? - Martin Smith
@martin,回顾你的row_number想法,是否可以按字段本身排序,而不是order by id?这样,任何已分配编号的文件都会排在列表顶部,下次单击“获取默认值”时,您将获得下一个编号。不太确定这是否有意义,但我希望答案在row_number领域中。 - James Parish
3个回答

11

SQL Server的函数 newid() 会生成一个GUID

你的SQL查询不会产生按钮或其他任何东西。 SQL是用于查询数据库的语言,而不是编写软件界面的语言。


5
它不能为你完成这件事,你也永远不应该这样做。每个列的值都应该是原子性的——它包含一个且仅有一个信息片段。文件所属办公室是一个单独的信息片段,应该放在自己的列中。如果你想在应用程序中显示“P0001”,你可以在应用程序中编写代码来组合办公室列和身份列。但你不应该将这两个不同的数据片段作为一个整体进行存储。 - Dan Grossman
@Dan - 我理解你的观点,但是难道不需要同时运行两个唯一ID生成器吗?一个用于A办公室,另一个用于B办公室,以确保两者都有顺序编号? - James Parish
两个办公室都是连续的,只是有间隔。为了避免间隔,他必须生成自己的标识符,但是使用建议的将所有内容混合到一个字符串列中时,他无论如何都要这样做。 - Dan Grossman
@Martin - 我一直在测试row_number,但似乎无法将生成的数字保存到字段中... 你有什么想法吗? - James Parish
@James - 顺便问一下,你能否对每个组内的编号必须连续这一要求提出异议吗?这真的很重要吗?如果你不太熟悉SQL,实现起来会很麻烦。只需拥有一个“identity”列并将其用作所有组的数字代码会更容易些。 - Martin Smith
显示剩余20条评论

0

我认为问题最初的措辞可能引起了一些误解。

我现在设想你需要一个流程,使得每个办公室在处理文件时都可以通过单击按钮生成一个新的保证顺序号?

然后跟进序列中的任何间隙,以调查潜在的丢失文件。是这样吗?

如果是这样,您可以使用类似以下代码来生成这些数字。

CREATE TABLE Sequences
(
OfficeCode char(1) primary key,
SequenceNumber int NOT NULL DEFAULT (0)
)

INSERT INTO Sequences(OfficeCode)
SELECT 'P' UNION ALL SELECT 'C' UNION ALL SELECT 'A'

GO

CREATE PROC dbo.GetSequence
@OfficeCode char(1),
@val AS int OUTPUT,
@n as int =1
AS
UPDATE dbo.Sequences 
SET @val = SequenceNumber = SequenceNumber + @n
WHERE OfficeCode = @OfficeCode;

SET @val = @val - @n + 1; 

GO


DECLARE @val  int

EXEC dbo.GetSequence 'C', @val output
select @val

首先,确认我需要的内容(我认为我们现在已经达成共识了):当一个文件需要归档时,每个办公室都会点击一个按钮,并按顺序获得下一个归档号码(然后将其写入文件,并将其放置在存储中)。偶尔文件会从存储中取出,但我们会保留它所在的空位,以便知道它丢失了(如果其他人请求它的话)。这样说您是否明白?我们是否达成一致意见?至于代码,很抱歉我不知道如何将其实现到我的系统中,超出了我的理解范围。 - James Parish
我已经尝试过了,但遗憾的是数据库不允许我查看更多内容,只能看到它的自定义字段构建器。我可以在构建器中看到和修改的SQL级别与最初的问题中发现的相同。 - James Parish

0
我会使用row_number函数和创建日期。如果您正在批量插入,则还需要按row_number函数中的id列排序。
declare @records table (id int identity(1,1), CreationDate datetime, Name varchar(50), Section char(1), FileID varchar(10))

insert into @records (CreationDate, Name, Section)
select '2011-01-26 16:57:49', 'abc','p'

insert into @records (CreationDate, Name, Section)
select '2011-01-26 16:57:50', 'def','p'

insert into @records (CreationDate, Name, Section)
select '2011-01-26 16:58:00', 'ghi','c'

insert into @records (CreationDate, Name, Section)
select '2011-01-26 16:58:50', 'jkl','d'

insert into @records (CreationDate, Name, Section)
select '2011-01-26 16:58:51', 'mno','c'

insert into @records (CreationDate, Name, Section)
select '2011-01-26 16:58:52', 'pqr','p'

insert into @records (CreationDate, Name, Section)
select '2011-01-26 16:58:53', 'def','p'

update @records
set FileID=a.FileID
from 
(
    select id,
    Section + cast(row_number() over (partition by Section order by CreationDate, Section) as varchar(10)) as FileID
    from @records
) a
    inner join @records b
        on a.id=b.id

select * from @records

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接