views:

1517

answers:

3

I am looking for a way to increment a uniqueidentifier by 1 in TSQL. For example, if the id is A6BC60AD-A4D9-46F4-A7D3-98B2A7237A9E, I'd like to be able to select A6BC60AD-A4D9-46F4-A7D3-98B2A7237A9F.

@rein It's for a data import. We have an intermediate table with IDs that we're generating records from, and we join on those IDs later in the import. Unfortunately, now some of those records generate a couple of records in the next table, so we need a new id that is reproducible.

A: 

Here is one way I've come up with, but I'm hoping there is a better way.

LEFT([ID], 19) + RIGHT(CONVERT(uniqueidentifier, CONVERT(binary(16), CONVERT(binary(16), [ID]) + CONVERT(bigint, 1))), 17) AS 'MyNewID'
a_hardin
What version of sql server; 2005 and 2008 have incrementing uniqueidentifiers as a data function - NEWSEQUENTIALID()
u07ch
I had hoped that would be my answer, too, but unfortunately it can't be used in queries.
a_hardin
if you can use clr then you can try this http://www.jorriss.net/blog/jorriss/archive/2008/04/24/unraveling-the-mysteries-of-newsequentialid.aspx
u07ch
A: 

This is dead simple. A guid easily converts to a byte array:

Guid startingId = new Guid();
Byte[] b = startingId.ToByteArray();
b[15] += 1;

Guid updatedId = new Guid(b);

If you are trying to get a table to use sequential guids when inserting new records, you can use the NEWSEQUENTIALID() function which will generate guids... sequentially.

Chris Lively
How about in T-SQL?
bdukes
Just wrap this up in a CLR...
Chris Lively
@Chris Lively: I consider "wrap"ping something into a CLR as one of the last resorts. Why bother programming in .NET, upload, register and harder to debug and maintain if you can find a way to do it in TSQL? ;)
Sung Meister
@dance2die: The whole point of MS adding the CLR to MS SQL was to cover cases like this where you could either do something really really ugly in T-SQL, or use C# and do it in an elegant way; but to each his own.
Chris Lively
A: 

You can do this approach, but I'm not accounting for the case of overflowing lower 8 bytes.

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