Вот один из них, который я придумал сегодня (потому что мне не понравился ни один из существующих ответов).
Этот файл генерирует временную таблицу случайных строк, основывается на newid()
, но также поддерживает настраиваемый набор символов (более 0-9 и AF), настраиваемую длину (до 255, ограничение жесткое). -кодировано, но может быть изменено) и произвольное количество случайных записей.
Вот исходный код (надеюсь, комментарии помогут):
/**
* First, we're going to define the random parameters for this
* snippet. Changing these variables will alter the entire
* outcome of this script. Try not to break everything.
*
* @var {int} count The number of random values to generate.
* @var {int} length The length of each random value.
* @var {char(62)} charset The characters that may appear within a random value.
*/
-- Define the parameters
declare @count int = 10
declare @length int = 60
declare @charset char(62) = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
/**
* We're going to define our random table to be twice the maximum
* length (255 * 2 = 510). It's twice because we will be using
* the newid() method, which produces hex guids. More later.
*/
-- Create the random table
declare @random table (
value nvarchar(510)
)
/**
* We'll use two characters from newid() to make one character in
* the random value. Each newid() provides us 32 hex characters,
* so we'll have to make multiple calls depending on length.
*/
-- Determine how many "newid()" calls we'll need per random value
declare @iterations int = ceiling(@length * 2 / 32.0)
/**
* Before we start making multiple calls to "newid", we need to
* start with an initial value. Since we know that we need at
* least one call, we will go ahead and satisfy the count.
*/
-- Iterate up to the count
declare @i int = 0 while @i < @count begin set @i = @i + 1
-- Insert a new set of 32 hex characters for each record, limiting to @length * 2
insert into @random
select substring(replace(newid(), '-', ''), 1, @length * 2)
end
-- Now fill the remaining the remaining length using a series of update clauses
set @i = 0 while @i < @iterations begin set @i = @i + 1
-- Append to the original value, limit @length * 2
update @random
set value = substring(value + replace(newid(), '-', ''), 1, @length * 2)
end
/**
* Now that we have our base random values, we can convert them
* into the final random values. We'll do this by taking two
* hex characters, and mapping then to one charset value.
*/
-- Convert the base random values to charset random values
set @i = 0 while @i < @length begin set @i = @i + 1
/**
* Explaining what's actually going on here is a bit complex. I'll
* do my best to break it down step by step. Hopefully you'll be
* able to follow along. If not, then wise up and come back.
*/
-- Perform the update
update @random
set value =
/**
* Everything we're doing here is in a loop. The @i variable marks
* what character of the final result we're assigning. We will
* start off by taking everything we've already done first.
*/
-- Take the part of the string up to the current index
substring(value, 1, @i - 1) +
/**
* Now we're going to convert the two hex values after the index,
* and convert them to a single charset value. We can do this
* with a bit of math and conversions, so function away!
*/
-- Replace the current two hex values with one charset value
substring(@charset, convert(int, convert(varbinary(1), substring(value, @i, 2), 2)) * (len(@charset) - 1) / 255 + 1, 1) +
-- (1) -------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------------
-- (2) ---------------------------------^^^^^^^^^^^^^^^^^^^^^^11111111111111111111111^^^^-------------------------------------
-- (3) --------------------^^^^^^^^^^^^^2222222222222222222222222222222222222222222222222^------------------------------------
-- (4) --------------------333333333333333333333333333333333333333333333333333333333333333---^^^^^^^^^^^^^^^^^^^^^^^^^--------
-- (5) --------------------333333333333333333333333333333333333333333333333333333333333333^^^4444444444444444444444444--------
-- (6) --------------------5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555^^^^----
-- (7) ^^^^^^^^^^^^^^^^^^^^66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666^^^^
/**
* (1) - Determine the two hex characters that we'll be converting (ex: 0F, AB, 3C, etc.)
* (2) - Convert those two hex characters to a a proper hexadecimal (ex: 0x0F, 0xAB, 0x3C, etc.)
* (3) - Convert the hexadecimals to integers (ex: 15, 171, 60)
* (4) - Determine the conversion ratio between the length of @charset and the range of hexadecimals (255)
* (5) - Multiply the integer from (3) with the conversion ratio from (4) to get a value between 0 and (len(@charset) - 1)
* (6) - Add 1 to the offset from (5) to get a value between 1 and len(@charset), since strings start at 1 in SQL
* (7) - Use the offset from (6) and grab a single character from @subset
*/
/**
* All that is left is to add in everything we have left to do.
* We will eventually process the entire string, but we will
* take things one step at a time. Round and round we go!
*/
-- Append everything we have left to do
substring(value, 2 + @i, len(value))
end
-- Select the results
select value
from @random
Это не хранимая процедура, но ее не так сложно превратить в одну. Это также не ужасно медленно (мне потребовалось ~ 0,3 секунды, чтобы сгенерировать 1000 результатов длины 60, что больше, чем я когда-либо лично нуждался), что было одной из моих первоначальных проблем от всей строковой мутации, которую я делаю.
Основной вывод здесь заключается в том, что я не пытаюсь создать свой собственный генератор случайных чисел, и мой набор символов не ограничен. Я просто использую генератор случайных чисел, который есть в SQL (я знаю, что есть rand()
, но это не очень хорошо для результатов таблицы). Надеемся, что этот подход объединяет два вида ответов: слишком простой (то есть просто newid()
) и слишком сложный (то есть пользовательский алгоритм случайных чисел).
Он также короткий (без комментариев) и прост для понимания (по крайней мере, для меня), что всегда является плюсом в моей книге.
Однако этот метод нельзя заполнить, поэтому каждый раз он будет действительно случайным, и вы не сможете реплицировать один и тот же набор данных с какой-либо надежностью. ОП не указывал это как требование, но я знаю, что некоторые люди ищут подобные вещи.
Я знаю, что опоздал на вечеринку, но, надеюсь, кто-то найдет это полезным.