Como generar un número random en SQL Server
| June 26, 2009 | Posted by royrojas under Bases de Datos, Programación |
Es cierto que SQL Server tiene la función RAND(), la cual genera un número aleatorio, pero este no funciona correctamente o por lo menos como uno lo espera.
Por ejemplo RAND() si es ejecutado en transacciones distintas funciona perfectamente pero si es ejecutado varias veces en una misma transacción siempre nos va a retornar el mismo valor, por lo tanto el random no funciona.
Para probar esto que acabo de decir vamos a abrir el Management Studio y en un query nuevo hacemos
SELECT newid() AS 'New id',
RAND() AS 'Random',
CHECKSUM(newid()) AS 'Checksum'
Resultado
| New Id | Random | Checksum | |
| 1 | F3201996-A5E7-4B44-BDDE-FFF2A2499AB1 | 0.542140206197715 | 133238726 |
Resultado siguiente ves que se ejecuta
| New Id | Random | Checksum | |
| 1 | 41B78E4A-9F73-47E0-8721-2190E699E696 | 0.216229945261277 | 926182060 |
Hasta aquí todo bien, las dos veces se ejecutó correctamente el random, como debe de ser, pero si se ejecuta varias veces en la misma transacción la historia es otra
SELECT TOP 5 newid() AS 'New id',
RAND() AS 'Mal Random',
CHECKSUM(newid()) AS 'Checksum'
from sys.tables
| New Id | Mal Random | Checksum | |
| 1 | C797611C-356C-47E4-97AD-14B331CECD7D | 0.029692678590302 | 1529445979 |
| 2 | 12600DA6-B399-4F31-9BED-186EECFAA896 | 0.029692678590302 | -1163175142 |
| 3 | 7691D246-73DE-4DD6-944B-0FA3523F0890 | 0.029692678590302 | 1893578383 |
| 4 | 69D663F5-0F40-4732-97FE-CB7F85B22E39 | 0.029692678590302 | 526397255 |
| 5 | F82D3E07-66BF-4579-95D6-C745D9FAAF6E | 0.029692678590302 | -1752607711 |
Como podemos ver el valor Random siempre es el mismo, esto se debe a que si a la función Random el seed que utiliza SQL para generar el random es siempre el mismo, el seed de la transacción, por lo tanto el valor retorno siempre es el mismo. Entonces cómo se puede generar un valor random correcto?
En los query de ejemplo podemos ver la columna Checksum, la cual nos está retornando valores diferente en cada resultado, ya sea en transacciones distintas o en la misma transacción. Aquí está la clave para nuestro random.
New Id es un valor que genera SQL tomando como base el MAC address de la tarjeta de red y el reloj de la computadora, esto nos genera un string muy largo pero siempre distinto. Si a este valor le aplicamos la función checksum [ checksum(newid()) ] nos genera un valor numérico entero, que en algunos casos puede ser negativo. Si ocupamos que nuestro valor random sea un numérico entero positivo simplemente le aplicamos la funcion absolute [ abs(checksum(newid())) ]
Entonces si ahora combinamos estas tres funciones de SQL obtendremos el random que necesitamos
SELECT TOP 5
RAND() AS 'Mal Random',
abs(checksum(newid())) AS 'RANDOM'
from sys.tables
Resultado
| Mal Random | RANDOM | |
| 1 | 0.747613544929705 | 149303544 |
| 2 | 0.747613544929705 | 2063275895 |
| 3 | 0.747613544929705 | 1150964410 |
| 4 | 0.747613544929705 | 1372336738 |
| 5 | 0.747613544929705 | 2115100305 |
Ultimos Comentarios