Увеличение уникального идентификатора в TSQL - PullRequest
1 голос
/ 05 мая 2009

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

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

Ответы [ 3 ]

4 голосов
/ 02 февраля 2012

Способ увеличения 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

Это означает, что байт № 3 GUID является наименее значимым, а байт № 10 GUID - наиболее значимым [с точки зрения предложения 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 (с двумя столбцами: одно целое число в качестве индекса и второе с сгенерированными Guids).

2 голосов
/ 05 мая 2009

Вы можете использовать этот подход, но я не учитываю случай переполнения младших 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(@binary16, 1, 8)
    ,@binaryLower8  = substring(@binary16, 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
1 голос
/ 05 мая 2009

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

LEFT([ID], 19) + RIGHT(CONVERT(uniqueidentifier, CONVERT(binary(16), CONVERT(binary(16), [ID]) + CONVERT(bigint, 1))), 17) AS 'MyNewID'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...