1. ホーム
  2. sql

[解決済み] T-SQLでランダムな文字列を生成する

2022-09-26 07:11:55

質問

T-SQL を使用して擬似ランダムな英数字の文字列を生成したいとしたら、どのように行いますか? ドル記号、ダッシュ、スラッシュのような文字をどのように除外しますか?

どのように解決するのですか?

ランダムなデータを生成するとき、特にテストでは、ランダムでありながら再現性のあるデータを作成することが非常に有効です。秘密はランダム関数に明示的な種を使用することで、同じ種でテストを再度実行したときに、まったく同じ文字列が再び生成されるようにします。以下は、再現可能な方法でオブジェクト名を生成する関数の簡単な例です。

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に更新しました。以下のコメントを参照してください。オリジナルの手順には、ランダムシードの進め方に問題がありました。コードを更新し、言及されているoff-by-oneの問題も修正しました。