来自字符串的 MSSQL GUID/UUID
MSSQL GUID/UUID from string
我需要使用 MSSQL 从给定的字符串创建永久性的 GUIDs/UUIDs,但找不到解决方法。因此,每次调用函数时,字符串“A12345”都会变成类似“AAAAAAAA-1234-5678-90AB-AAAAAAAAAAA”的内容。
需要一些建议或示例如何实现。
正如有人在评论中所说,您可能应该重新考虑,但是......如果字符串的类型为 varchar(16)
或更小(不是 nvarchar),则至少有一种方法可以大致实现我对您的理解 objective 成为.
我对您的案例了解不多,无法推荐此解决方案,但假设您确实需要这样做。如果不出意外,这可能会帮助您构建自己的功能或共同决定这是一个坏主意。下面的解决方案要求您构建另一个函数,以便在检索数据时基本上反向执行相同的操作,如果您想要返回原始值。
唯一标识符在视觉上由 0-9 和 A-F 之间的 32 个 alpha-numeric 个字符以及四个破折号组成的字符串表示。这意味着该字符串中每个位置有 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')
如果您只是想创建一个映射,您可以这样做 (example fiddle):
创建一个 table 来保存映射
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 都将被放置在现有索引的末尾。但是,如果您愿意/可以在存储过程中生成 GUID 而不是作为插入中的默认值,则可以使用 newid()
生成 GUID,从而减少那里的调用。选择哪种取决于您的要求
注:以上为映射;但是这种映射只对具有映射 table 的人有意义/这不是普遍适用的东西;还是那句话,这个是不是suitable要看你的要求了
我需要使用 MSSQL 从给定的字符串创建永久性的 GUIDs/UUIDs,但找不到解决方法。因此,每次调用函数时,字符串“A12345”都会变成类似“AAAAAAAA-1234-5678-90AB-AAAAAAAAAAA”的内容。 需要一些建议或示例如何实现。
正如有人在评论中所说,您可能应该重新考虑,但是......如果字符串的类型为 varchar(16)
或更小(不是 nvarchar),则至少有一种方法可以大致实现我对您的理解 objective 成为.
我对您的案例了解不多,无法推荐此解决方案,但假设您确实需要这样做。如果不出意外,这可能会帮助您构建自己的功能或共同决定这是一个坏主意。下面的解决方案要求您构建另一个函数,以便在检索数据时基本上反向执行相同的操作,如果您想要返回原始值。
唯一标识符在视觉上由 0-9 和 A-F 之间的 32 个 alpha-numeric 个字符以及四个破折号组成的字符串表示。这意味着该字符串中每个位置有 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')
如果您只是想创建一个映射,您可以这样做 (example fiddle):
创建一个 table 来保存映射
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 都将被放置在现有索引的末尾。但是,如果您愿意/可以在存储过程中生成 GUID 而不是作为插入中的默认值,则可以使用 newid()
生成 GUID,从而减少那里的调用。选择哪种取决于您的要求
注:以上为映射;但是这种映射只对具有映射 table 的人有意义/这不是普遍适用的东西;还是那句话,这个是不是suitable要看你的要求了