使用 T-SQL 生成随机字符串

新手上路,请多包涵

如果你想使用 T-SQL 生成一个伪随机字母数字字符串,你会怎么做?您将如何从中排除美元符号、破折号和斜杠等字符?

原文由 Scott Lawrence 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 528
2 个回答

在生成随机数据时,特别是为了测试,使数据随机但可重复是非常有用的。秘诀是对随机函数使用显式种子,这样当使用相同的种子再次运行测试时,它会再次产生完全相同的字符串。下面是一个以可重现方式生成对象名称的函数的简化示例:

 alter procedure usp_generateIdentifier
    @minLen int = 1
    , @maxLen int = 256
    , @seed int output
    , @string varchar(8000) output
as
begin
    set nocount on;
    declare @length int;
    declare @alpha varchar(8000)
        , @digit varchar(8000)
        , @specials varchar(8000)
        , @first varchar(8000)
    declare @step bigint = rand(@seed) * 2147483647;

    select @alpha = 'qwertyuiopasdfghjklzxcvbnm'
        , @digit = '1234567890'
        , @specials = '_@# '
    select @first = @alpha + '_@';

    set  @seed = (rand((@seed+@step)%2147483647)*2147483647);

    select @length = @minLen + rand(@seed) * (@maxLen-@minLen)
        , @seed = (rand((@seed+@step)%2147483647)*2147483647);

    declare @dice int;
    select @dice = rand(@seed) * len(@first),
        @seed = (rand((@seed+@step)%2147483647)*2147483647);
    select @string = substring(@first, @dice, 1);

    while 0 < @length
    begin
        select @dice = rand(@seed) * 100
            , @seed = (rand((@seed+@step)%2147483647)*2147483647);
        if (@dice < 10) -- 10% special chars
        begin
            select @dice = rand(@seed) * len(@specials)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);
            select @string = @string + substring(@specials, @dice, 1);
        end
        else if (@dice < 10+10) -- 10% digits
        begin
            select @dice = rand(@seed) * len(@digit)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);
            select @string = @string + substring(@digit, @dice, 1);
        end
        else -- rest 80% alpha
        begin
            declare @preseed int = @seed;
            select @dice = rand(@seed) * len(@alpha)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);

            select @string = @string + substring(@alpha, @dice, 1);
        end

        select @length = @length - 1;
    end
end
go

运行测试时,调用者生成一个随机种子,它与测试运行相关联(将其保存在结果表中),然后传递种子,类似于:

 declare @seed int;
declare @string varchar(256);

select @seed = 1234; -- saved start seed

exec usp_generateIdentifier
    @seed = @seed output
    , @string = @string output;
print @string;
exec usp_generateIdentifier
    @seed = @seed output
    , @string = @string output;
print @string;
exec usp_generateIdentifier
    @seed = @seed output
    , @string = @string output;
print @string;

2016-02-17 更新:请参阅下面的评论,原始程序在推进随机种子的方式上存在问题。我更新了代码,还修复了上面提到的问题。

原文由 Remus Rusanu 发布,翻译遵循 CC BY-SA 3.0 许可协议

另一个具有完整字母表的简单解决方案:

 SELECT LEFT(REPLACE(REPLACE((SELECT CRYPT_GEN_RANDOM(16) FOR XML PATH(''), BINARY BASE64),'+',''),'/',''),16);

将两个 16 替换为所需的长度。

样本结果:

 pzyMATe3jJwN1XkB

原文由 Tofnet 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进