使用SQL在视图上创建唯一GUID

时间:2013-03-11 13:24:26

标签: sql-server sql-server-2008 tsql

我需要为MS Sql表创建一个View(没有Id),新的View必须包含一个UNIQUE Id。 目前我正在使用ROW编号和stuff函数来创建ID。

不幸的是,拥有一个大表的结果是一些重复的ID。

我相信问题可能在'72799568-6EF2-4C95-84E7-4953A6959C90',我知道如何解决它?

CREATE VIEW viewWithId as
SELECT convert(uniqueidentifier,
       stuff('72799568-6EF2-4C95-84E7-4953A6959C90',1,len(rn),convert(varchar,rn))) [Id],
       T.[EventId], 
       T.[EventTitle]
FROM 
    ( 
        select  x.[EventId], 
                x.[EventTitle]
                ROW_NUMBER() over (order by x.EventId) rn
        FROM    dbo.A as x 
    ) T

3 个答案:

答案 0 :(得分:3)

你得到重复的原因是因为第1行,第12行和第127行(通常是行n,10 * n + 2和100 * n + 27)都返回相同的标识符。如果您需要GUID,那么只需使用

CREATE VIEW viewWithId as
SELECT NEWID() [Id],
       T.[EventId], 
       T.[EventTitle]
FROM 
    ( 
        select  x.[EventId], 
                x.[EventTitle]
                ROW_NUMBER() over (order by x.EventId) rn
        FROM    dbo.A as x 
    ) T

但问题是,当您重新选择视图时,每行都会获得不同的UUID。

如果您尝试从ID“生成”GUID,则必须提出一种保证对任何Id都是唯一的算法。另一种选择是从0开始并将Id添加到 end

SELECT convert(uniqueidentifier,
           stuff('72799568-6EF2-4C95-84E7-000000000000',
                 36-LEN(rn),
                 len(rn),
                 convert(varchar,rn)
                )
            ) [Id],
       T.[EventId], 
       T.[EventTitle]
FROM 
    ( 
        select  x.[EventId], 
                x.[EventTitle]
                ROW_NUMBER() over (order by x.EventId) rn
        FROM    dbo.A as x 
    ) T

这将为999,999,999,999(~1万亿)行提供足够的“唯一”ID。

答案 1 :(得分:2)

您可以使用NEWID()投影随机新GUID。显然,虽然投射随机guid 与投射行标识符(主键)相同。实际上,如果表没有数据库强制主键,则基本上无法来投影正确的主键值。 任何努力都会因并发和更新(特别是删除)而无效。

答案 2 :(得分:1)

如果你想让guid依赖于eventid,请使用以下代码:

CREATE VIEW viewWithId as
SELECT convert(uniqueidentifier,
       '72799568-6EF2-4C95-'
        + STUFF(CONVERT(VARCHAR(36), CAST(rn AS VARBINARY(8)), 2),5, 0, '-')
       ) [Id],
       T.[EventId], 
       T.[EventTitle]
FROM 
    ( 
        select  x.[EventId], 
                x.[EventTitle],
                ROW_NUMBER() over (order by x.EventId) rn
        FROM    dbo.A as x 
    ) T

它将ROW_NUMBER的完整HEX表示合并到guid中。

如果EventId是唯一的且永远不会更改某一行,则新的EventId总是大于所有现有的(例如IDENTITY值),您永远不会删除一行,并且所有插入都使用表锁,这将为每一行创建相同的值时间。如果没有给出上述任何一项,解决此问题的唯一方法是向表中添加一个guid列,除非您不关心连续运行之间的值是否发生变化。