Si vous vouliez générer une chaîne alphanumérique pseudo-aléatoire à l'aide de T-SQL, comment le feriez-vous? Comment excluriez-vous des caractères tels que les signes dollar, les tirets et les barres obliques?
Lors de la génération de données aléatoires, spécialement pour le test, il est très utile de rendre les données aléatoires, mais reproductibles. Le secret est d'utiliser des valeurs de départ explicites pour la fonction aléatoire, de sorte que lorsque le test est réexécuté avec la même valeur de départ, il produit à nouveau exactement les mêmes chaînes. Voici un exemple simplifié d'une fonction qui génère des noms d'objets de manière reproductible:
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
Lors de l'exécution des tests, l'appelant génère une graine aléatoire qu'il associe à l'exécution du test (l'enregistre dans le tableau des résultats), puis transmise la graine, semblable à 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;
Mise à jour 17/02/2016: Voir les commentaires ci-dessous, la procédure d'origine avait un problème dans la façon dont elle avançait la graine aléatoire. J'ai mis à jour le code et j'ai également corrigé le problème mentionné ci-dessus.
@seed = rand(@seed+1)*2147483647
. Pour la valeur 529126, la valeur suivante est 1230039262 et la valeur suivante est 192804. La séquence continue de manière identique après cela. La sortie doit différer par le premier caractère, mais ce n'est pas le cas à cause d'une erreurSUBSTRING(..., 0, ...)
de décalage : renvoie une chaîne vide pour l'index 0, et pour 529126, cela «masque» le premier caractère généré. Le correctif consiste à calculer@dice = rand(@seed) * len(@specials)+1
pour rendre les index 1 basés.+1
dans lerand(@seed+1)
lui-même aléatoire et déterminé à partir de la graine initiale uniquement. De cette façon, même si les séries atteignent la même valeur, elles divergent immédiatement.Utiliser un guid
très court ...
la source
Similaire au premier exemple, mais avec plus de flexibilité:
J'ai oublié de mentionner l'une des autres fonctionnalités 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.
la source
CONVERT(int, RAND() * @PoolLength) + 1
(notez le +1 ajouté). SUBSTRING dans T-SQL commence par l'index 1, donc dans sa forme actuelle, cette fonction ajoute parfois une chaîne vide (lorsque l'index est 0), et n'ajoute jamais le dernier caractère du@CharPool
.Utilisez le code suivant pour renvoyer une courte chaîne:
la source
Si vous exécutez SQL Server 2008 ou une version ultérieure, vous pouvez utiliser la nouvelle fonction cryptographique crypt_gen_random (), puis utiliser le codage base64 pour en faire une chaîne. Cela fonctionnera jusqu'à 8 000 caractères.
la source
Je ne suis pas expert en T-SQL, mais la manière la plus simple que j'ai déjà utilisée, c'est comme ça:
Cela génère deux caractères (AZ, en ascii 65-90).
la source
Cela renverra les 5 caractères les plus à gauche de la chaîne guid
la source
Voici un générateur alphanumérique aléatoire
la source
Pour une lettre aléatoire, vous pouvez utiliser:
Une différence importante entre l'utilisation
newid()
et l' utilisationrand()
est que si vous renvoyez plusieurs lignes,newid()
est calculé séparément pour chaque ligne, alors qu'ilrand()
est calculé une fois pour l'ensemble de la requête.la source
Cela a fonctionné pour moi: je devais générer seulement trois caractères alphanumériques aléatoires pour un identifiant, mais cela pouvait fonctionner pour n'importe quelle longueur jusqu'à 15 ou plus.
la source
Il y a beaucoup de bonnes réponses, mais jusqu'à présent, aucune d'entre elles n'autorise un pool de caractères personnalisable et ne fonctionne comme valeur par défaut pour une colonne. Je voulais pouvoir faire quelque chose comme ça:
Alors je suis venu avec ça. Méfiez-vous du nombre codé en dur 32 si vous le modifiez.
la source
Je me rends compte que c'est une vieille question avec beaucoup de bonnes réponses. Cependant, quand j'ai trouvé cela, j'ai également trouvé un article plus récent sur TechNet par Saeid Hasani
T-SQL: Comment générer des mots de passe aléatoires
Alors que la solution se concentre sur les mots de passe, elle s'applique au cas général. Saeid travaille à travers diverses considérations pour arriver à une solution. C'est très instructif.
Un script contenant tous les blocs de code de l'article est disponible séparément via la galerie TechNet , mais je commencerais certainement par l'article.
la source
J'utilise cette procédure que j'ai développée simplement stiplatez les caractères que vous souhaitez pouvoir afficher dans les variables d'entrée, vous pouvez également définir la longueur. J'espère que cela formate bien, je suis nouveau pour le débordement de pile.
la source
Parfois, nous avons besoin de beaucoup de choses aléatoires: amour, gentillesse, vacances, etc. J'ai collecté quelques générateurs aléatoires au fil des ans, et ceux-ci proviennent de Pinal Dave et d'une réponse stackoverflow que j'ai trouvée une fois. Réf ci-dessous.
la source
En voici une que j'ai trouvée aujourd'hui (parce que je n'aimais pas assez les réponses existantes).
Celui-ci génère une table temporaire de chaînes aléatoires, est basé sur
newid()
, mais prend également en charge un jeu de caractères personnalisé (donc plus que juste 0-9 et AF), une longueur personnalisée (jusqu'à 255, la limite est codée en dur, mais peut être changé) et un nombre personnalisé d'enregistrements aléatoires.Voici le code source (j'espère que les commentaires aident):
Ce n'est pas une procédure stockée, mais il ne serait pas si difficile d'en faire une. Ce n'est pas non plus terriblement lent (il m'a fallu ~ 0,3 seconde pour générer 1000 résultats de longueur 60, ce qui est plus que ce dont j'aurai jamais besoin personnellement), ce qui était l'une de mes préoccupations initiales de toutes les mutations de cordes que je fais.
Le principal à retenir ici est que je n'essaye pas de créer mon propre générateur de nombres aléatoires et que mon jeu de caractères n'est pas limité. J'utilise simplement le générateur aléatoire de SQL (je sais qu'il y en a
rand()
, mais ce n'est pas génial pour les résultats de table). Espérons que cette approche marie les deux types de réponses ici, de trop simple (c'est-à-dire justenewid()
) et trop complexe (c'est-à-dire un algorithme de nombres aléatoires personnalisé).C'est aussi court (moins les commentaires) et facile à comprendre (du moins pour moi), ce qui est toujours un plus dans mon livre.
Cependant, cette méthode ne peut pas être amorcée, elle sera donc vraiment aléatoire à chaque fois et vous ne pourrez pas répliquer le même ensemble de données avec aucun moyen de fiabilité. Le PO n'a pas mentionné cela comme une exigence, mais je sais que certaines personnes recherchent ce genre de chose.
Je sais que je suis en retard à la fête ici, mais j'espère que quelqu'un trouvera cela utile.
la source
Pour SQL Server 2016 et versions ultérieures, voici une expression vraiment simple et relativement efficace pour générer des chaînes cryptographiquement aléatoires d'une longueur d'octet donnée:
Notez que la longueur d'octet n'est pas la même que la taille codée; utilisez les éléments suivants de cet article pour convertir:
la source
Je suis d'abord tombé sur ce billet de blog , puis j'ai proposé la procédure stockée suivante pour cela que j'utilise sur un projet en cours (désolé pour le formatage étrange):
la source
J'ai fait cela dans SQL 2000 en créant une table qui contenait des caractères que je voulais utiliser, en créant une vue qui sélectionne les caractères de cette table en triant par newid (), puis en sélectionnant le premier caractère de cette vue.
Ensuite, vous pouvez simplement extraire des caractères de la vue et les concaténer si nécessaire.
EDIT: Inspiré par la réponse de Stephan ...
Pas besoin de vue (en fait je ne sais pas pourquoi j'ai fait ça - le code date de plusieurs années). Vous pouvez toujours spécifier les caractères que vous souhaitez utiliser dans le tableau.
la source
Voici quelque chose basé sur New Id.
la source
Je pensais partager ou redonner à la communauté ... C'est basé sur ASCII, et la solution n'est pas parfaite mais ça marche plutôt bien. Amusez-vous bien, Goran B.
la source
Cela utilise rand avec une graine comme l'une des autres réponses, mais il n'est pas nécessaire de fournir une graine à chaque appel. Le fournir au premier appel est suffisant.
Ceci est mon code modifié.
la source
Dans SQL Server 2012+, nous pourrions concaténer les binaires de certains UID (G), puis faire un base64 conversion sur le résultat.
Si vous avez besoin de chaînes plus longues (ou si vous voyez des
=
caractères dans le résultat), vous devez en ajouter d'autres+ CAST(newid() as varbinary(max))
dans la sous-sélection.la source
J'ai donc aimé beaucoup de réponses ci-dessus, mais je cherchais quelque chose d'un peu plus aléatoire par nature. Je voulais aussi un moyen d'appeler explicitement les personnages exclus. Voici ma solution utilisant une vue qui appelle le
CRYPT_GEN_RANDOM
pour obtenir un nombre aléatoire cryptographique. Dans mon exemple, je n'ai choisi qu'un nombre aléatoire de 8 octets. Veuillez noter que vous pouvez augmenter cette taille et également utiliser le paramètre de départ de la fonction si vous le souhaitez. Voici le lien vers la documentation: https://docs.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sqlLa raison de la création de la vue est qu'elle
CRYPT_GEN_RANDOM
ne peut pas être appelée directement à partir d'une fonction.À partir de là, j'ai créé une fonction scalaire qui accepte une longueur et un paramètre de chaîne pouvant contenir une chaîne délimitée par des virgules de caractères exclus.
Vous trouverez ci-dessous un exemple de la façon d'appeler la fonction.
~ Acclamations
la source
c'est très simple. Utilisez-le et profitez-en.
la source
Cela produira une chaîne de 96 caractères de longueur, à partir de la plage Base64 (supérieurs, inférieurs, nombres, + et /). Ajouter 3 "NEWID ()" augmentera la longueur de 32, sans remplissage en Base64 (=).
Si vous appliquez ceci à un ensemble, assurez-vous d'introduire quelque chose de cet ensemble afin que le NEWID () soit recalculé, sinon vous obtiendrez la même valeur à chaque fois:
la source
Sur la base de diverses réponses utiles dans cet article, j'ai atterri avec une combinaison de quelques options que j'ai aimées.
la source