在TSQL中增加唯一标识符

问题描述:

我正在寻找一种在TSQL中将唯一标识符增加1的方法。例如,如果ID是A6BC60AD-A4D9-46F4-A7D3-98B2A7237A9E,我希望能够选择A6BC60AD-A4D9-46F4-A7D3-98B2A7237A9F。在TSQL中增加唯一标识符

@rein它用于数据导入。我们有一个中间表,其中包含我们正在生成记录的ID,并且稍后在导入时加入这些ID。不幸的是,现在这些记录中的一些在下一个表中生成了一些记录,所以我们需要一个可重现的新的记录。

+2

我真的很想知道你为什么需要这样做。 – rein 2009-05-04 22:48:04

+2

如果您发现自己处于需要增加GUID的情况下,10次中有9次我将重新检查您正在尝试执行的操作。 – 2009-05-05 03:26:14

以下是我想到的一种方法,但我希望有更好的方法。

LEFT([ID], 19) + RIGHT(CONVERT(uniqueidentifier, CONVERT(binary(16), CONVERT(binary(16), [ID]) + CONVERT(bigint, 1))), 17) AS 'MyNewID' 

你可以这样做,但我没有考虑溢出低8字节的情况。

declare @guid uniqueidentifier, @binaryUpper8 binary(8), @binaryLower8 binary(8), @binary16 binary(16), @bigint bigint 
set @guid = 'A6BC60AD-A4D9-46F4-A7D3-98B2A7237A9E' 
set @binary16 = cast(@guid as binary(16)) 

--harvest lower 8 bytes 
select @binaryUpper8= substring(0xAD60BCA6D9A4F446A7D398B2A7237A9E, 1, 8) 
    ,@binaryLower8 = substring(0xAD60BCA6D9A4F446A7D398B2A7237A9E, 9, 8) 
set @bigint = cast(@binaryLower8 as bigint) 

--increment 
set @bigint = @bigint + 1 

--convert back 
set @binaryLower8 = cast(@bigint as binary(8)) 
set @binary16 = @binaryUpper8 + @binaryLower8 
set @guid = cast(@binary16 as uniqueidentifier) 
select @guid 

要增加GUID是不是为SQL Server正确的,因为GUID是在字节组不同字节顺序的结构方式,请看看: http://sqlblog.com/blogs/alberto_ferrari/archive/2007/08/31/how-are-guids-sorted-by-sql-server.aspx 并注意以下事项:

现在,当我运行改性Alberto的查询时,我发现了下列序列: 3,2,1,0,5,4,7,6,9,8,15,14,13,12, 11,10

这意味着,GUID的字节#3是最少的si有意义的和GUID的字节#10是最重要的[从SQL Server ORDER BY子句的角度]。

这里是简单的函数来增加一个唯一标识符占该:

create function [dbo].[IncrementGuid](@guid uniqueidentifier) 
returns uniqueidentifier 
as 
begin 
declare @guid_binary binary(16), @b03 binary(4), @b45 binary(2), @b67 binary(2), @b89 binary(2), @bAF binary(6) 

select @guid_binary = @guid 

select @b03 = convert(binary(4), reverse(substring(@guid_binary,1,4))) 
select @b45 = convert(binary(2), reverse(substring(@guid_binary,5,2))) 
select @b67 = convert(binary(2), reverse(substring(@guid_binary,7,2))) 
select @b89 = convert(binary(2), substring(@guid_binary,9,2)) 
select @bAF = convert(binary(6), substring(@guid_binary,11,6)) 

if (@b03 < 'FFFFFFFF') 
begin 
    select @b03 = convert(binary(4), cast(@b03 as int) + 1) 
end 
else if (@b45 < 'FFFF') 
begin 
    select @b45 = convert(binary(2), cast(@b45 as int) + 1) 
end 
else if (@b89 < 'FFFF') 
begin 
    select @b89 = convert(binary(2), cast(@b89 as int) + 1) 
end 
else 
begin 
    select @bAF = convert(binary(6), cast(@bAF as bigint) + 1) 
end 

return convert(binary(16), reverse(convert(char(4),@b03)) + reverse(convert(char(2),@b45)) + reverse(convert(char(2),@b67)) + convert(char(2),@b89) + convert(char(6),@bAF)) 
end 

注意,字节6和7不递增,因为它们含有的GUID版本比特。 但正如其他人指出你真的不应该这样做。在你的情况下,如果你为这些Guids创建一个临时表(有两列:一个整数作为索引,第二个具有生成的GUID),可能会更好。