|

Obtendo Valor Aleatório no SQL Server com RAND()

Compartilhe :

Neste post você vai ver como gerar valores aleatórios no SQL Server usando a função RAND() do Transact-SQL: da sintaxe básica até um problema comum que pega muita gente de surpresa quando RAND() é usado em uma consulta com várias linhas.

Sintaxe da função RAND

RAND ( [ seed ] )

Argumento:

  • seed: valor inteiro (tinyint, smallint ou int) opcional, usado como semente do gerador. Se não for informado, o SQL Server usa uma semente aleatória automaticamente. Já quando um valor de seed é especificado, o resultado é sempre o mesmo para aquele valor.

O que a função RAND retorna

RAND() retorna um valor do tipo float, sempre entre 0 e 1:

SELECT RAND();
-- Exemplo de resultado: 0.494443

Uma observação importante: chamadas repetidas de RAND() com o mesmo seed retornam sempre o mesmo resultado. A consulta abaixo, por exemplo, sempre gera a mesma sequência de números para o mesmo seed:

SELECT RAND(100), RAND(), RAND();

Gerando um número inteiro com RAND

Para transformar o resultado de RAND() (que é sempre entre 0 e 1) em um número inteiro dentro de um intervalo, basta multiplicar pelo tamanho do intervalo desejado e converter com CAST ou FLOOR.

Número inteiro entre 0 e 9:

SELECT CAST(RAND() * 10 AS INT);

Número inteiro entre 0 e 19:

SELECT CAST(RAND() * 20 AS INT);

Para outras faixas, basta ajustar o multiplicador. De forma mais genérica, para gerar um número inteiro entre um valor mínimo e um valor máximo (incluindo os dois extremos), use:

SELECT FLOOR(RAND() * (@max - @min + 1) + @min);

Substituindo @min e @max pelos limites desejados, ou por variáveis declaradas antes da consulta.

O gotcha mais comum: RAND() repete o mesmo valor em todas as linhas

Esse é o ponto que mais confunde quem usa RAND() pela primeira vez em uma consulta real. Ao usar RAND() sem seed em um SELECT que retorna várias linhas, o SQL Server calcula o valor uma única vez para a consulta inteira, não uma vez por linha. O resultado é que todas as linhas recebem exatamente o mesmo número aleatório:

SELECT ProductID, RAND() AS ValorAleatorio
FROM Production.Product;

Nesse exemplo, toda a coluna ValorAleatorio sai com o mesmo valor repetido, o que raramente é o comportamento esperado.

Como resolver: RAND() com CHECKSUM(NEWID())

A forma mais comum de contornar isso é usar NEWID(), que gera um identificador único por linha, como semente de RAND():

SELECT ProductID, RAND(CHECKSUM(NEWID())) AS ValorAleatorio
FROM Production.Product;

Como NEWID() gera um valor diferente para cada linha, e CHECKSUM transforma esse valor em um inteiro para servir de seed, RAND() passa a calcular um número diferente para cada linha da consulta.

Gerando vários números aleatórios em um loop

Fora do contexto de uma consulta com múltiplas linhas, é possível gerar vários números aleatórios em sequência usando um WHILE:

DECLARE @Contador SMALLINT = 1;

WHILE @Contador < 5
BEGIN
    SELECT RAND() AS NumeroAleatorio;
    SET @Contador = @Contador + 1;
END;

Conclusão

RAND() é simples de usar para gerar um valor aleatório pontual, e com CAST ou FLOOR é fácil transformar esse valor em um inteiro dentro de qualquer faixa. O detalhe que realmente importa conhecer é o comportamento de RAND() em consultas com várias linhas: sem seed, ele repete o mesmo valor para todas as linhas, e a forma padrão de contornar isso é combinando RAND() com CHECKSUM(NEWID()).

Referência: Documentação oficial da função RAND (Microsoft Docs)

Posts Similares