2009-05-04 4 views
1

Я ищу способ увеличить уникальный идентификатор на 1 в TSQL. Например, если идентификатором является A6BC60AD-A4D9-46F4-A7D3-98B2A7237A9E, я бы хотел, чтобы у меня была возможность выбрать A6BC60AD-A4D9-46F4-A7D3-98B2A7237A9F.Приращение уникального идентификатора в TSQL

@rein Это импорт данных. У нас есть промежуточная таблица с идентификаторами, из которых мы создаем записи, и присоединяемся к этим идентификаторам позже в процессе импорта. К сожалению, теперь некоторые из этих записей генерируют пару записей в следующей таблице, поэтому нам нужен новый идентификатор, который воспроизводится.

+2

Мне было бы интересно узнать, зачем вам это нужно. – rein

+2

Если вы оказались в ситуации, требующей увеличения GUID, в 9 раз из 10 я бы пересмотрел то, что вы пытаетесь сделать. –

+2

Вместо того, чтобы увеличивать GUID, возможно, было бы проще просто добавить дополнительный столбец столбцов для устранения неоднозначности? – ahains

ответ

1

Вот один из способов, с которым я пришел, но я надеюсь, что есть лучший способ.

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

Какая версия сервера sql; 2005 и 2008 увеличивают уникальные идентификаторы в качестве функции данных - NEWSEQUENTIALID() – u07ch

+0

Я надеялся, что это будет мой ответ, но, к сожалению, он не может использоваться в запросах. –

+0

если вы можете использовать clr, то вы можете попробовать это http://www.jorriss.net/blog/jorriss/archive/2008/04/24/unraveling-the-mysteries-of-newsequentialid.aspx – u07ch

1

Вы можете сделать такой подход, но я не учитываю случай переполнения нижних 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 
4

, как вы хотите, чтобы увеличить Guid не является правильным для SQL Server, как Guid представляет собой структуру с другой последовательностью байт в байт группы, пожалуйста, посмотрите на: http://sqlblog.com/blogs/alberto_ferrari/archive/2007/08/31/how-are-guids-sorted-by-sql-server.aspx и обратите внимание на следующее:

Теперь, когда я запускаю измененный запрос Альберто, я получаю следующую последовательность: 3, 2, 1, 0, 5, 4, 7, 6, 9, 8, 15, 14, 13, 12, 11, 10

Это означает, что байт GUID № 3 является наименьшим значением si gnificant и байт # 10 GUID является наиболее значительным [с точки зрения предложения ORDER BY SQL Server].

Вот простая функция прирастить UniqueIdentifier учета для этого:

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. Но, как вы указали, вы действительно не должны делать это. В вашем случае было бы лучше, если бы вы создали временную таблицу для этих Гидов (с двумя столбцами: одно целое в качестве индекса и второе с созданными Гидами).

Смежные вопросы