我需要使用 MSSQL 从给定字符串创建永久 GUID/UUID,但没有找到执行此操作的解决方案。因此,每次调用函数时,字符串“A12345”都会变成“AAAAAAA-1234-5678-90AB-AAAAAAAAAA”之类的内容。 需要一些建议或示例如何实现这一目标。
正如有人在评论中所说,您可能应该重新考虑,但是..如果字符串的类型为
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')
如果您只是想创建一个映射,您可以执行类似的操作(示例小提琴):
创建一个表来保存映射
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,而不是作为插入中的默认值,从而减少那里的调用。选哪个取决于您的要求
注:以上为映射;但这种映射仅对拥有映射表的人有意义/这不是普遍正确的东西;再说一遍,这是否合适取决于您的要求。
这是一个创建 uuid v3 和 v5 的 ms sql 函数: https://gist.github.com/osexpert/3cc0aee7817e4d492d5915acb34708c1 您发送一个 uuid 作为“命名空间”和一个字符串,然后返回一个 uuid。 Uuid v3 和 v5 是从随机字符串创建 uuid 的标准方法,但它并不为人所知。 使用标准方法的优点是您可以创建真正的 uuid,并且它们的设计不会与其他真正的 uuid 发生冲突。