Wenn Sie eine pseudozufällige alphanumerische Zeichenfolge mit T-SQL generieren möchten, wie würden Sie dies tun? Wie würden Sie Zeichen wie Dollarzeichen, Bindestriche und Schrägstriche davon ausschließen?
Bei der Erzeugung zufälliger Daten, insbesondere für Tests, ist es sehr nützlich, die Daten zufällig, aber reproduzierbar zu machen. Das Geheimnis besteht darin, explizite Seeds für die Zufallsfunktion zu verwenden, sodass beim erneuten Ausführen des Tests mit demselben Seed wieder genau dieselben Zeichenfolgen erzeugt werden. Hier ist ein vereinfachtes Beispiel für eine Funktion, die Objektnamen reproduzierbar generiert:
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
Beim Ausführen der Tests generiert der Aufrufer einen zufälligen Startwert, den er dem Testlauf zuordnet (speichert ihn in der Ergebnistabelle), und leitet ihn dann ähnlich wie folgt weiter:
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;
Update 17.02.2016: Siehe die folgenden Kommentare. Das ursprüngliche Verfahren hatte ein Problem mit der Weiterentwicklung des zufälligen Startwerts. Ich habe den Code aktualisiert und auch das erwähnte Off-by-One-Problem behoben.
@seed = rand(@seed+1)*2147483647
. Für den Wert 529126 ist der nächste Wert 1230039262 und der nächste Wert ist 192804. Die Sequenz wird danach identisch fortgesetzt. Die Ausgabe sollte sich nach dem ersten Zeichen unterscheiden, jedoch nicht aufgrund eines Off-by-One-Fehlers:SUBSTRING(..., 0, ...)
Gibt eine leere Zeichenfolge für Index 0 zurück, und für 529126 wird das erste generierte Zeichen "ausgeblendet". Fix ist zu berechnen@dice = rand(@seed) * len(@specials)+1
, um die Indizes 1 basierend zu machen.+1
in therand(@seed+1)
be selbst zufällig gemacht und nur aus dem anfänglichen Samen bestimmt wird. Auf diese Weise weichen die Serien sofort voneinander ab, selbst wenn sie denselben Wert erreichen.Mit einem Guid
sehr kurze ...
quelle
Ähnlich wie im ersten Beispiel, jedoch mit mehr Flexibilität:
Ich habe vergessen, eine der anderen Funktionen zu erwähnen, die dies flexibler machen. Durch Wiederholen von Zeichenblöcken in @CharPool können Sie die Gewichtung bestimmter Zeichen erhöhen, damit sie mit größerer Wahrscheinlichkeit ausgewählt werden.
quelle
CONVERT(int, RAND() * @PoolLength) + 1
(beachten Sie die hinzugefügten +1). SUBSTRING in T-SQL beginnt mit Index 1, daher fügt diese Funktion in der jetzigen Form manchmal eine leere Zeichenfolge hinzu (wenn der Index 0 ist) und fügt niemals das letzte Zeichen aus dem hinzu@CharPool
.Verwenden Sie den folgenden Code, um eine kurze Zeichenfolge zurückzugeben:
quelle
Wenn Sie SQL Server 2008 oder höher ausführen, können Sie die neue kryptografische Funktion crypt_gen_random () verwenden und dann die Base64-Codierung verwenden, um daraus eine Zeichenfolge zu machen. Dies funktioniert für bis zu 8000 Zeichen.
quelle
Ich bin kein Experte für T-SQL, aber der einfachste Weg, den ich bereits benutzt habe, ist folgender:
Dies erzeugt zwei Zeichen (AZ, in ASCII 65-90).
quelle
Dies gibt die 5 am weitesten links stehenden Zeichen der Guid-Zeichenfolge zurück
quelle
Hier ist ein zufälliger alphanumerischer Generator
quelle
Für einen zufälligen Buchstaben können Sie verwenden:
Ein wichtiger Unterschied zwischen der Verwendung
newid()
und der Verwendungrand()
besteht darin, dass bei Rückgabe mehrerer Zeilen diesenewid()
für jede Zeile separat berechnet wird, währendrand()
sie für die gesamte Abfrage einmal berechnet wird.quelle
Das hat bei mir funktioniert: Ich musste nur drei zufällige alphanumerische Zeichen für eine ID generieren, aber es konnte für jede Länge bis zu 15 oder so funktionieren.
quelle
Es gibt viele gute Antworten, aber bisher erlaubt keine einen anpassbaren Zeichenpool und funktioniert als Standardwert für eine Spalte. Ich wollte in der Lage sein, so etwas zu tun:
Also habe ich mir das ausgedacht. Achten Sie auf die fest codierte Nummer 32, wenn Sie sie ändern.
quelle
Mir ist klar, dass dies eine alte Frage mit vielen guten Antworten ist. Als ich dies fand, fand ich auch einen neueren Artikel über TechNet von Saeid Hasani
T-SQL: So generieren Sie zufällige Passwörter
Während sich die Lösung auf Passwörter konzentriert, gilt sie für den allgemeinen Fall. Saeid arbeitet verschiedene Überlegungen durch, um zu einer Lösung zu gelangen. Es ist sehr lehrreich.
Ein Skript, das alle Codeblöcke aus dem Artikel enthält, ist separat über die TechNet-Galerie verfügbar , aber ich würde definitiv mit dem Artikel beginnen.
quelle
Ich verwende dieses von mir entwickelte Verfahren, indem ich einfach die Zeichen stipluiere, die Sie in den Eingabevariablen anzeigen möchten. Sie können auch die Länge definieren. Hoffe, diese Formate gut, ich bin neu im Stapelüberlauf.
quelle
Manchmal brauchen wir viele zufällige Dinge: Liebe, Freundlichkeit, Urlaub usw. Ich habe im Laufe der Jahre einige zufällige Generatoren gesammelt, die von Pinal Dave stammen und eine Stapelüberlauf-Antwort, die ich einmal gefunden habe. Refs unten.
quelle
Hier ist eine, die ich mir heute ausgedacht habe (weil mir keine der vorhandenen Antworten genug gefallen hat).
Dieser generiert eine temporäre Tabelle mit zufälligen Zeichenfolgen, basiert auf
newid()
, unterstützt aber auch einen benutzerdefinierten Zeichensatz (also mehr als nur 0-9 & AF) und eine benutzerdefinierte Länge (bis zu 255, Limit ist fest codiert, kann aber sein geändert) und eine benutzerdefinierte Anzahl von zufälligen Datensätzen.Hier ist der Quellcode (hoffentlich helfen die Kommentare):
Es ist keine gespeicherte Prozedur, aber es wäre nicht so schwer, sie in eine zu verwandeln. Es ist auch nicht schrecklich langsam (ich habe ~ 0,3 Sekunden gebraucht, um 1.000 Ergebnisse mit einer Länge von 60 zu generieren, was mehr ist, als ich jemals persönlich brauchen werde), was eines meiner anfänglichen Probleme bei all der String-Mutation war, die ich mache.
Das Wichtigste dabei ist, dass ich nicht versuche, einen eigenen Zufallszahlengenerator zu erstellen, und mein Zeichensatz ist nicht begrenzt. Ich verwende einfach den Zufallsgenerator, den SQL hat (ich weiß
rand()
, dass es ihn gibt , aber das ist nicht gut für Tabellenergebnisse). Hoffentlich verbindet dieser Ansatz die beiden Arten von Antworten hier, von zu einfach (dh nurnewid()
) und übermäßig komplex (dh benutzerdefinierter Zufallszahlenalgorithmus).Es ist auch kurz (abzüglich der Kommentare) und leicht zu verstehen (zumindest für mich), was in meinem Buch immer ein Plus ist.
Diese Methode kann jedoch nicht festgelegt werden, sodass sie jedes Mal wirklich zufällig ist und Sie nicht in der Lage sind, denselben Datensatz mit irgendeiner Art von Zuverlässigkeit zu replizieren. Das OP hat dies nicht als Anforderung aufgeführt, aber ich weiß, dass einige Leute nach solchen Dingen suchen.
Ich weiß, dass ich zu spät zur Party komme, aber hoffentlich findet das jemand nützlich.
quelle
Ich bin zuerst auf diesen Blog-Beitrag gestoßen und habe dann die folgende gespeicherte Prozedur dafür gefunden, die ich für ein aktuelles Projekt verwende (Entschuldigung für die seltsame Formatierung):
quelle
Ich habe dies in SQL 2000 getan, indem ich eine Tabelle mit Zeichen erstellt habe, die ich verwenden wollte, eine Ansicht erstellt habe, in der Zeichen aus dieser Tabelle ausgewählt werden, die nach newid () sortiert ist, und dann das oberste 1-Zeichen aus dieser Ansicht ausgewählt habe.
Dann können Sie einfach Zeichen aus der Ansicht ziehen und sie nach Bedarf verketten.
EDIT: Inspiriert von Stephans Antwort ...
Keine Notwendigkeit für eine Ansicht (tatsächlich bin ich mir nicht sicher, warum ich das getan habe - der Code stammt aus mehreren Jahren). Sie können weiterhin die Zeichen angeben, die Sie in der Tabelle verwenden möchten.
quelle
Hier ist etwas basierend auf New Id.
quelle
Ich dachte, ich würde teilen oder der Community etwas zurückgeben ... Es basiert auf ASCII und die Lösung ist nicht perfekt, funktioniert aber recht gut. Viel Spaß, Goran B.
quelle
Dies verwendet Rand mit einem Startwert wie eine der anderen Antworten, es ist jedoch nicht erforderlich, bei jedem Aufruf einen Startwert bereitzustellen. Die Bereitstellung beim ersten Anruf ist ausreichend.
Dies ist mein geänderter Code.
quelle
In SQL Server 2012+ könnten wir die Binärdateien einiger (G) UIDs verketten und dann eine base64- Konvertierung für das Ergebnis durchführen.
Wenn Sie längere Zeichenfolgen benötigen (oder
=
Zeichen im Ergebnis sehen), müssen Sie+ CAST(newid() as varbinary(max))
in der Unterauswahl weitere hinzufügen .quelle
Ich mochte viele der obigen Antworten, aber ich suchte nach etwas, das etwas zufälliger war. Ich wollte auch eine Möglichkeit, ausgeschlossene Zeichen explizit aufzurufen. Unten ist meine Lösung mit einer Ansicht, die die aufruft
CRYPT_GEN_RANDOM
, um eine kryptografische Zufallszahl zu erhalten. In meinem Beispiel habe ich nur eine Zufallszahl ausgewählt, die 8 Byte betrug. Bitte beachten Sie, dass Sie diese Größe erhöhen und bei Bedarf auch den Startparameter der Funktion verwenden können. Hier ist der Link zur Dokumentation: https://docs.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sqlDer Grund für das Erstellen der Ansicht liegt darin, dass
CRYPT_GEN_RANDOM
sie nicht direkt von einer Funktion aufgerufen werden kann.Von dort aus habe ich eine Skalarfunktion erstellt, die eine Länge und einen Zeichenfolgenparameter akzeptiert, die eine durch Kommas getrennte Zeichenfolge ausgeschlossener Zeichen enthalten können.
Unten finden Sie ein Beispiel für den Aufruf der Funktion.
~ Prost
quelle
Es ist sehr einfach. Verwenden Sie es und genießen Sie.
quelle
Dadurch wird eine Zeichenfolge mit einer Länge von 96 Zeichen aus dem Base64-Bereich (Ober-, Unter-, Zahlen, + und /) erzeugt. Durch Hinzufügen von 3 "NEWID ()" wird die Länge um 32 erhöht, ohne dass eine Base64-Auffüllung (=) erforderlich ist.
Wenn Sie dies auf eine Menge anwenden, stellen Sie sicher, dass Sie etwas aus dieser Menge einführen, damit die NEWID () neu berechnet wird. Andernfalls erhalten Sie jedes Mal den gleichen Wert:
quelle
Für SQL Server 2016 und höher ist hier ein wirklich einfacher und relativ effizienter Ausdruck zum Generieren kryptografisch zufälliger Zeichenfolgen mit einer bestimmten Bytelänge:
Beachten Sie, dass die Bytelänge nicht mit der codierten Größe übereinstimmt. Verwenden Sie zum Konvertieren Folgendes aus diesem Artikel:
quelle
Basierend auf verschiedenen hilfreichen Antworten in diesem Artikel landete ich mit einer Kombination einiger Optionen, die mir gefallen haben.
quelle