Si vous souhaitiez générer une chaîne alphanumérique pseudo-aléatoire à l'aide de T-SQL, comment procéderiez-vous? Comment excluriez-vous des caractères tels que les signes dollar, les tirets et les barres obliques?
Réponses
Trop de publicités?Semblable au premier exemple, mais avec plus de flexibilité:
-- min_length = 8, max_length = 12
SET @Length = RAND() * 5 + 8
-- SET @Length = RAND() * (max_length - min_length + 1) + min_length
-- define allowable character explicitly - easy to read this way an easy to
-- omit easily confused chars like l (ell) and 1 (one) or 0 (zero) and O (oh)
SET @CharPool =
'abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789.,-_!$@#%^&*'
SET @PoolLength = Len(@CharPool)
SET @LoopCount = 0
SET @RandomString = ''
WHILE (@LoopCount < @Length) BEGIN
SELECT @RandomString = @RandomString +
SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength), 1)
SELECT @LoopCount = @LoopCount + 1
END
J'ai oublié de mentionner l'une des autres caractéristiques qui rend cela plus flexible. En répétant des blocs de caractères dans @CharPool, vous pouvez augmenter la pondération de certains caractères afin qu'ils soient plus susceptibles d'être choisis.
Lors de la génération de données aléatoires, spécialement pour le test, il est très utile pour rendre les données aléatoires, mais reproductible. Le secret est d'utiliser des semences pour la fonction de lecture aléatoire, de sorte que lorsque le test est exécuté à nouveau avec la même graine, il produit à nouveau exactement les mêmes chaînes. Voici un exemple simplifié d'une fonction qui génère des noms d'objet, de manière reproductible:
create 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)
select @alpha = 'qwertyuiopasdfghjklzxcvbnm'
, @digit = '1234567890'
, @specials = '_@# '
select @first = @alpha + '_@';
select @length = @minLen + rand(@seed) * (@maxLen-@minLen)
, @seed = (rand(@seed+1)*2147483647);
declare @dice int;
select @dice = rand(@seed) * len(@first),
@seed = (rand(@seed+1)*2147483647);
select @string = substring(@first, @dice, 1);
while 0 < @length
begin
select @dice = rand(@seed) * 100
, @seed = (rand(@seed+1)*2147483647);
if (@dice < 10) -- 10% special chars
begin
select @dice = rand(@seed) * len(@specials)
, @seed = (rand(@seed+1)*2147483647);
select @string = @string + substring(@specials, @dice, 1);
end
else if (@dice < 10+10) -- 10% digits
begin
select @dice = rand(@seed) * len(@digit)
, @seed = (rand(@seed+1)*2147483647);
select @string = @string + substring(@digit, @dice, 1);
end
else -- rest 80% alpha
begin
select @dice = rand(@seed) * len(@alpha)
, @seed = (rand(@seed+1)*2147483647);
select @string = @string + substring(@alpha, @dice, 1);
end
select @length = @length - 1;
end
end
go
Lors de l'exécution des tests de l'appelant génère une valeur aléatoire, il s'associe avec l'essai (l'enregistre dans le tableau de résultats), puis transmis le long de la graine, similaire à ceci:
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;