在SQL Server中将varchar转换为uniqueidentifier

131
一个我无法控制模式的表,包含一个定义为varchar(50)的列,该列以格式'a89b1acd95016ae6b9c8aabb07da2010'(没有连字符)存储唯一标识符。
我想将这些转换为SQL中的唯一标识符,以便传递给.Net GUID。然而,以下查询语句对我无效:
select cast('a89b1acd95016ae6b9c8aabb07da2010' as uniqueidentifier)
select convert(uniqueidentifier, 'a89b1acd95016ae6b9c8aabb07da2010')

并导致:

Msg 8169,级别 16,状态 2,行 1
在将字符字符串转换为 uniqueidentifier 时转换失败。

使用连字符连接的 uniqueidentifier 的相同查询正常工作,但数据不以该格式存储。

在 SQL 中是否有另一种(高效)将这些字符串转换为 uniqueidentifier 的方法?-- 我不想在 .Net 代码中进行转换。


1
仅有一行字符和数字并不是有效的GUID表示形式 - 您将不得不采用字符串解析魔法,就像Quassnoi在他的答案中展示的那样。 - marc_s
7个回答

151
DECLARE @uuid VARCHAR(50)
SET @uuid = 'a89b1acd95016ae6b9c8aabb07da2010'
SELECT  CAST(
        SUBSTRING(@uuid, 1, 8) + '-' + SUBSTRING(@uuid, 9, 4) + '-' + SUBSTRING(@uuid, 13, 4) + '-' +
        SUBSTRING(@uuid, 17, 4) + '-' + SUBSTRING(@uuid, 21, 12)
        AS UNIQUEIDENTIFIER)

16
我真的希望这不是解决方案,但我想我们很快就会知道了… - grenade
31
声明 @u 唯一标识符 将 @u 设置为 CONVERT(uniqueidentifier, 'c029f8be-29dc-41c1-8b38-737b4cc5a4df') 的值。*** 这就足够了。我试过了。 - Fabio Milheiro
哦,是的!那我必须同意。显而易见的方法是将连字符放在正确的位置,然后你就可以开始了!对不起! - Fabio Milheiro
将此代码片段放入函数中是工具箱的一个不错的补充,特别是因为一些JSON序列化器在序列化时会删除GUID中的破折号,这使得将其复制粘贴到SQL中进行调试更加困难。 - David Cumps
1
@StoneGiant:如果像OP一样,您不想在客户端进行转换,那么这就是解决方案。如果您愿意在客户端执行此操作,则任何半靠谱的ORM都可以将此字符串映射到.NET Guid,无论是开箱即用还是使用一行映射规则。 - Quassnoi
显示剩余2条评论

31

这将成为一个很方便的函数。另外,请注意我正在使用STUFF而不是SUBSTRING。

create function str2uniq(@s varchar(50)) returns uniqueidentifier as begin
    -- just in case it came in with 0x prefix or dashes...
    set @s = replace(replace(@s,'0x',''),'-','')
    -- inject dashes in the right places
    set @s = stuff(stuff(stuff(stuff(@s,21,0,'-'),17,0,'-'),13,0,'-'),9,0,'-')
    return cast(@s as uniqueidentifier)
end

或者一个单行代码:

cast(stuff(stuff(stuff(stuff(replace(replace(@s,'0x',''),'-',''),21,0,'-'),17,0,'-'),13,0,'-'),9,0,'-') as uniqueidentifier)

5
Stuff() 的使用非常出色。使用你的方法,在 Select 语句中只需要引用一次我的领域。我避免使用标量函数,因为它们不总是很好地“扩展”,所以我会将其写出来。谢谢,这将成为我的代码片段! - MikeTeeVee

21

您的varchar列C:

SELECT CONVERT(uniqueidentifier,LEFT(C, 8)
                                + '-' +RIGHT(LEFT(C, 12), 4)
                                + '-' +RIGHT(LEFT(C, 16), 4)
                                + '-' +RIGHT(LEFT(C, 20), 4)
                                + '-' +RIGHT(C, 12))

17
SELECT CONVERT(uniqueidentifier,STUFF(STUFF(STUFF(STUFF('B33D42A3AC5A4D4C81DD72F3D5C49025',9,0,'-'),14,0,'-'),19,0,'-'),24,0,'-'))

1
SELECT CAST(CAST('A89B1ACD-9501-6AE6-B9C8-AABB07DA2010' as char(36)) as uniqueidentifier)

2
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

0

-7

提供的 GUID 格式不正确(.NET 提供的 GUID)。

begin try
select convert(uniqueidentifier,'a89b1acd95016ae6b9c8aabb07da2010')
end try
begin catch
print '1'
end catch

9
这段代码只打印出1,它并没有回答如何将没有连字符的varchar转换为GUID的问题。 - Aaroninus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接