来自字符串的 MSSQL GUID/UUID

问题描述 投票:0回答:3

我需要使用 MSSQL 从给定字符串创建永久 GUID/UUID,但没有找到执行此操作的解决方案。因此,每次调用函数时,字符串“A12345”都会变成“AAAAAAA-1234-5678-90AB-AAAAAAAAAA”之类的内容。 需要一些建议或示例如何实现这一目标。

sql-server tsql uuid guid
3个回答
1
投票

正如有人在评论中所说,您可能应该重新考虑,但是..如果字符串的类型为

varchar(16)
或更小(不是nvarchar),那么有一种方法至少可以大致实现我所理解的您的目标。

我对您的案例了解不够,无法推荐此解决方案,但假设您确实需要这样做。如果没有其他事情,这可能会帮助您构建自己的功能,或者认为这是一个坏主意。如果您想要返回原始值,下面的解决方案要求您构建另一个函数,以便在检索数据时基本上反向执行相同的操作。

唯一标识符在视觉上由 0-9 和 A-F 之间的 32 个字母数字字符以及四个破折号组成的字符串表示。这意味着该字符串中的每个位置有 16 个选项,共有 32 个位置。我建议不要在此函数中使用字母 A 作为填充符,下面我使用 0 代替,因为 00 在 ASCII 中是 NULL,而 AA 代表实际字符。

首先,您可以使用

ASCII()
函数将字符串中的每个字符转换为其 ASCII 值。此后,您可以通过对该值使用除法和模 16 将返回的整数转换为十六进制字符串表示形式。 SQL Server 中的 ASCII 范围为 0-255,这意味着有 256 个不同的字符。 256 是 16 乘以 16,这意味着您需要 uniqueidentifier 中的两个位置来表示输入字符串中的每个字符,因此此函数中的最大字符串限制为 16 个而不是 32 个(请参阅前面的段落)。最后,您需要在正确的位置插入破折号并将字符串转换为唯一标识符。

 CREATE FUNCTION dbo.MYGUID (@input varchar(17))
    RETURNS uniqueidentifier
    BEGIN
        /* Unable to convert any string langer than 16 characters with this method */
        IF LEN(@input) > 16
            RETURN CAST('FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF' as uniqueidentifier)
    
    DECLARE 
        @result varchar(36) = '',
        @char char(1) = '',
        @placeholder varchar(32) = REPLICATE('0',32)

    /* Convert all characters in string to psuedo-hexadecimal */
    WHILE LEN(@input) > 0 BEGIN
        /* Use first character in input string.. */
        SET @char = LEFT(@input, 1)
        /* Convert character to hexadecimal representation */
        SET @result += CONVERT(char(1),
            CASE ASCII(@char) / 16
                WHEN 10 THEN 'A'
                WHEN 11 THEN 'B'
                WHEN 12 THEN 'C'
                WHEN 13 THEN 'D'
                WHEN 14 THEN 'E'
                WHEN 15 THEN 'F'
                ELSE CONVERT(char, ASCII(@char) / 16)
            END)
        +CONVERT(char(1), 
            CASE ASCII(@char) % 16
                WHEN 10 THEN 'A'
                WHEN 11 THEN 'B'
                WHEN 12 THEN 'C'
                WHEN 13 THEN 'D'
                WHEN 14 THEN 'E'
                WHEN 15 THEN 'F'
                ELSE CONVERT(char, ASCII(@char) % 16)
            END
        )
        /* Remove first character from input string.. */
        SET @input = STUFF(@input, 1, 1, '')
    END

    /* Make sure there are exactly 32 alpha-numeric characters in outgoing string */
    SET @result = RIGHT(@placeholder+@result,32)

    /* Insert dashes at the correct positions */
    SET @result = STUFF(@result, 21, 0, '-')
    SET @result = STUFF(@result, 17, 0, '-')
    SET @result = STUFF(@result, 13, 0, '-')
    SET @result = STUFF(@result, 9, 0, '-')

    /* Returns string as uniqueidentifier */
    RETURN CAST(@result as uniqueidentifier)
END

创建函数后,您可以通过..

使用它
SELECT dbo.MYGUID(column1)
FROM table1

..或者..

SELECT dbo.MYGUID('A12345')

0
投票

如果您只是想创建一个映射,您可以执行类似的操作(示例小提琴):

创建一个表来保存映射

create table StringGuidMap (
    Guid uniqueidentifier not null constraint PK_StringGuidMap primary key clustered default NewSequentialId()
    , StringId nvarchar(8) not null constraint UK_StringGuidMap_StringId unique
)

创建逻辑来获取映射或根据需要创建新映射:

create procedure sp_GetIdMapping (
  @StringId nvarchar(8)
) as
begin

  declare @result uniqueidentifier = null

  select @result = Guid 
  from StringGuidMap 
  where StringId = @StringId -- note: case/accent sensitivity depends on your DB's collation

  if (@result is null)
  begin
      
      insert into StringGuidMap(StringId) 
      values (@StringId)
      
      select @result = Guid 
      from StringGuidMap 
      where StringId = @StringId
      
  end

  select @result Guid

end

在上面我使用了

NewSequentialId
来生成 GUID,确保该列可以轻松地用作索引中的主键/而不导致碎片,因为生成的每个新 ID 都会放在现有 ID 的末尾指数。但是,如果您愿意,可以使用
newid()
生成 GUID / 可以在存储过程中生成 GUID,而不是作为插入中的默认值,从而减少那里的调用。选哪个取决于您的要求

注:以上为映射;但这种映射仅对拥有映射表的人有意义/这不是普遍正确的东西;再说一遍,这是否合适取决于您的要求。


0
投票

这是一个创建 uuid v3 和 v5 的 ms sql 函数: https://gist.github.com/osexpert/3cc0aee7817e4d492d5915acb34708c1 您发送一个 uuid 作为“命名空间”和一个字符串,然后返回一个 uuid。 Uuid v3 和 v5 是从随机字符串创建 uuid 的标准方法,但它并不为人所知。 使用标准方法的优点是您可以创建真正的 uuid,并且它们的设计不会与其他真正的 uuid 发生冲突。

© www.soinside.com 2019 - 2024. All rights reserved.