Si quisiera generar una cadena alfanumérica pseudoaleatoria usando T-SQL, ¿cómo lo haría? ¿Cómo excluiría caracteres como signos de dólar, guiones y barras?
Al generar datos aleatorios, especialmente para pruebas, es muy útil hacer que los datos sean aleatorios, pero reproducibles. El secreto es utilizar semillas explícitas para la función aleatoria, de modo que cuando la prueba se vuelva a ejecutar con la misma semilla, vuelva a producir exactamente las mismas cadenas. A continuación, se muestra un ejemplo simplificado de una función que genera nombres de objeto de manera reproducible:
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
Cuando se ejecutan las pruebas, la persona que llama genera una semilla aleatoria que asocia con la ejecución de la prueba (la guarda en la tabla de resultados) y luego la pasa a lo largo de la semilla, similar a esta:
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;
Actualización 2016-02-17: vea los comentarios a continuación, el procedimiento original tenía un problema en la forma en que avanzaba la semilla aleatoria. Actualicé el código y también solucioné el problema mencionado uno por uno.
@seed = rand(@seed+1)*2147483647
. Para el valor 529126, el siguiente valor es 1230039262 y luego el siguiente valor es 192804. La secuencia continúa idénticamente después de esto. La salida debe diferir por el primer carácter, pero no debido a un error de uno por uno:SUBSTRING(..., 0, ...)
devuelve una cadena vacía para el índice 0 y para 529126 esto 'oculta' el primer carácter generado. La solución es calcular@dice = rand(@seed) * len(@specials)+1
para hacer los índices basados en 1.+1
in therand(@seed+1)
sea aleatorio y determinado solo a partir de la semilla inicial. De esta forma, incluso si la serie alcanza el mismo valor, divergen inmediatamente.Usando una guía
muy corto ...
fuente
Similar al primer ejemplo, pero con más flexibilidad:
Olvidé mencionar una de las otras características que hace que esto sea más flexible. Al repetir bloques de caracteres en @CharPool, puede aumentar la ponderación de ciertos caracteres para que sea más probable que se elijan.
fuente
CONVERT(int, RAND() * @PoolLength) + 1
(tenga en cuenta el +1 añadido). SUBSTRING en T-SQL comienza con el índice 1, por lo que, tal como está, esta función a veces agrega una cadena vacía (cuando el índice es 0) y nunca agrega el último carácter del@CharPool
.Utilice el siguiente código para devolver una cadena corta:
fuente
Si está ejecutando SQL Server 2008 o superior, puede usar la nueva función criptográfica crypt_gen_random () y luego usar la codificación base64 para convertirla en una cadena. Esto funcionará para hasta 8000 caracteres.
fuente
No soy un experto en T-SQL, pero la forma más sencilla que ya he usado es así:
Esto genera dos caracteres (AZ, en ascii 65-90).
fuente
Esto devolverá los 5 caracteres más a la izquierda de la cadena guid
fuente
Aquí hay un generador alfanumérico aleatorio
fuente
Para una letra aleatoria, puede usar:
Una diferencia importante entre usar
newid()
versusrand()
es que si devuelve varias filas,newid()
se calcula por separado para cada fila, mientras querand()
se calcula una vez para toda la consulta.fuente
Esto funcionó para mí: necesitaba generar solo tres caracteres alfanuméricos aleatorios para una identificación, pero podría funcionar para cualquier longitud de hasta 15 más o menos.
fuente
Hay muchas respuestas buenas, pero hasta ahora ninguna de ellas permite un grupo de caracteres personalizable y funciona como un valor predeterminado para una columna. Quería poder hacer algo como esto:
Entonces se me ocurrió esto. Tenga cuidado con el número 32 codificado de forma rígida si lo modifica.
fuente
Me doy cuenta de que esta es una vieja pregunta con muchas buenas respuestas. Sin embargo, cuando encontré esto, también encontré un artículo más reciente en TechNet por Saeid Hasani
T-SQL: Cómo generar contraseñas aleatorias
Si bien la solución se centra en las contraseñas, se aplica al caso general. Saeid trabaja a través de varias consideraciones para llegar a una solución. Es muy instructivo.
Un script que contiene todos los bloques de código del artículo está disponible por separado a través de la Galería de TechNet , pero definitivamente comenzaría con el artículo.
fuente
Utilizo este procedimiento que desarrollé simplemente para estipular los caracteres que desea poder mostrar en las variables de entrada, también puede definir la longitud. Espero que este formato esté bien, soy nuevo en el desbordamiento de pila.
fuente
A veces necesitamos muchas cosas aleatorias: amor, amabilidad, vacaciones, etc. He recopilado algunos generadores aleatorios a lo largo de los años, y estos son de Pinal Dave y una respuesta de stackoverflow que encontré una vez. Refs debajo.
fuente
Aquí hay uno que se me ocurrió hoy (porque no me gustó lo suficiente ninguna de las respuestas existentes).
Éste genera una tabla temporal de cadenas aleatorias, se basa en
newid()
, pero también admite un conjunto de caracteres personalizado (por lo tanto, más que solo 0-9 y AF), longitud personalizada (hasta 255, el límite está codificado de forma rígida, pero puede ser cambiado) y un número personalizado de registros aleatorios.Aquí está el código fuente (con suerte, los comentarios ayudan):
No es un procedimiento almacenado, pero no sería tan difícil convertirlo en uno. Tampoco es terriblemente lento (me tomó ~ 0.3 segundos generar 1,000 resultados de longitud 60, que es más de lo que necesitaré personalmente), que fue una de mis preocupaciones iniciales de toda la mutación de cuerdas que estoy haciendo.
La conclusión principal aquí es que no estoy tratando de crear mi propio generador de números aleatorios, y mi conjunto de caracteres no está limitado. Simplemente estoy usando el generador aleatorio que tiene SQL (sé que lo hay
rand()
, pero eso no es bueno para los resultados de la tabla). Es de esperar que este enfoque combine los dos tipos de respuestas aquí, desde demasiado simple (es decir, solonewid()
) y demasiado complejo (es decir, algoritmo de número aleatorio personalizado).También es breve (menos los comentarios) y fácil de entender (al menos para mí), lo que siempre es una ventaja en mi libro.
Sin embargo, este método no se puede sembrar, por lo que será realmente aleatorio cada vez y no podrá replicar el mismo conjunto de datos con ningún medio de confiabilidad. El OP no incluyó eso como un requisito, pero sé que algunas personas buscan ese tipo de cosas.
Sé que llego tarde a la fiesta aquí, pero espero que alguien lo encuentre útil.
fuente
Para SQL Server 2016 y versiones posteriores, aquí hay una expresión realmente simple y relativamente eficiente para generar cadenas criptográficamente aleatorias de una longitud de byte determinada:
Tenga en cuenta que la longitud del byte no es la misma que el tamaño codificado; utilice lo siguiente de este artículo para convertir:
fuente
Primero encontré esta publicación de blog , luego se me ocurrió el siguiente procedimiento almacenado para esto que estoy usando en un proyecto actual (lo siento por el formato extraño):
fuente
Hice esto en SQL 2000 creando una tabla que tenía los caracteres que quería usar, creando una vista que selecciona los caracteres de esa tabla ordenados por newid () y luego seleccionando el primer carácter de esa vista.
Luego, simplemente puede extraer caracteres de la vista y concatenarlos según sea necesario.
EDITAR: Inspirado por la respuesta de Stephan ...
No es necesario verlo (de hecho, no estoy seguro de por qué hice eso, el código es de varios años atrás). Aún puede especificar los caracteres que desea usar en la tabla.
fuente
Aquí hay algo basado en New Id.
fuente
Pensé en compartir o retribuir a la comunidad ... Está basado en ASCII y la solución no es perfecta, pero funciona bastante bien. Disfruta, Goran B.
fuente
Esto usa rand con una semilla como una de las otras respuestas, pero no es necesario proporcionar una semilla en cada llamada. Proporcionarlo en la primera llamada es suficiente.
Este es mi código modificado.
fuente
En SQL Server 2012+ , podríamos concatenar los binarios de algunos (G) UID y luego hacer una conversión en base64 en el resultado.
Si necesita cadenas más largas (o ve
=
caracteres en el resultado), debe agregar más+ CAST(newid() as varbinary(max))
en la sub-selección.fuente
Así que me gustaron muchas de las respuestas anteriores, pero estaba buscando algo que fuera un poco más aleatorio por naturaleza. También quería una forma de llamar explícitamente a los personajes excluidos. A continuación se muestra mi solución con una vista que llama a
CRYPT_GEN_RANDOM
para obtener un número aleatorio criptográfico. En mi ejemplo, solo elegí un número aleatorio de 8 bytes. Tenga en cuenta que puede aumentar este tamaño y también utilizar el parámetro semilla de la función si lo desea. Aquí está el enlace a la documentación: https://docs.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sqlLa razón para crear la vista es porque
CRYPT_GEN_RANDOM
no se puede llamar directamente desde una función.A partir de ahí, creé una función escalar que acepta una longitud y un parámetro de cadena que puede contener una cadena delimitada por comas de caracteres excluidos.
A continuación se muestra un ejemplo de cómo llamar a la función.
~ Saludos
fuente
es muy simple úsalo y disfruta.
fuente
Esto producirá una cadena de 96 caracteres de longitud, desde el rango de Base64 (superiores, inferiores, números, + y /). Agregar 3 "NEWID ()" aumentará la longitud en 32, sin relleno Base64 (=).
Si está aplicando esto a un conjunto, asegúrese de introducir algo de ese conjunto para que se vuelva a calcular el NEWID (); de lo contrario, obtendrá el mismo valor cada vez:
fuente
Basado en varias respuestas útiles en este artículo, obtuve una combinación de un par de opciones que me gustaron.
fuente