Вопрос SqlServer Rand ()

Я пишу процедуру, в которой каждому вызову требуется получить одно случайное число. Эта процедура вызывается из нашего веб-сервиса .net.

Я попытался реализовать это, используя rand (). Однако, когда у меня есть несколько вызовов хранимой процедуры в миллисекундах, я получаю много коллизий в том, что генерируется одно и то же случайное число. Если между последующими вызовами имеется пробел около 20 или 30 мс, он, похоже, работает нормально.

Похоже, что rand () повторно загружает каждый вызов хранимой процедуры SqlServer. Из того, что я понимаю, это проблема, потому что один раз нужно генерировать генератор случайных чисел, и что не получается хорошая последовательность псевдослучайных чисел, если каждый раз переписывает каждый вызов rand. Кроме того, похоже, что вызовы одного и того же sp, которые находятся в пределах 1 или 2 миллисекунды, посеяны с одинаковым значением.

Вот инструкция в хранимой процедуре.

DECLARE @randomNumber char(9) SET @randomNumber = RIGHT('00000' + CAST(CAST(rand()*100000 AS INT) AS VARCHAR(5)),5) + RIGHT('00000' + CAST(CAST(rand()*10000 AS INT) AS VARCHAR(4)),4) 

Есть ли у кого-нибудь предложение об этом?

Должен ли я написать свой собственный генератор случайных чисел, который засевается один раз и сохраняет его состояние в таблице через вызовы? Как SQL Server семя rand ()? Действительно ли это случайный или если вы вызываете sp в течение 1 или 2 миллисекунды друг от друга на отдельных соединениях, будет ли он посеян одним и тем же семенем, вызывающим столкновение?

Если вы используете SQL Server 2008, вы можете использовать функцию CRYPT_GEN_RANDOM (). Это будет рандомизировать данные для каждой строки, даже если вы пытались вычислить миллионы случайных чисел в одном выполнении запроса и не имеете проблем с посевом:

 SELECT CAST(RIGHT(CAST(CAST(CRYPT_GEN_RANDOM(1) AS INT) AS VARCHAR(100)), 1) AS INT) 

Вот ссылка на статью BOL:

http://msdn.microsoft.com/en-us/library/cc627408.aspx

В вашем примере замените rand()*10000 на ABS(CHECKSUM(NEWID())) % 9999

Однако для char (9):

 SELECT RIGHT('000000000' + CAST(ABS(CHECKSUM(NEWID()) % 999999999) AS char(9), 9) 

Для случайного семени RAND …

 RAND(CHECKSUM(NEWID())) 

Редактировать:

Примечание. RAND плохо реализован в SQL Server. Не используйте его.

Вы можете использовать таблицу только с полем идентификатора для создания уникальных nunbers для использования в качестве семпла:

 declare @randomNumber char(9), @seed1 int, @seed2 int insert into SeedTable () values () set @seed1 = scope_identity() insert into SeedTable () values () set @seed2 = scope_identity() set @randomNumber = right('00000' + cast(cast(rand(@seed1) * 100000 as int) as varchar(5)), 5) + right('00000' + cast(cast(rand(@seed2) * 10000 as int) as varchar(4)), 4) if (@seed2 > 10000) truncate table SeedTable 

Функция RAND () имеет необязательный параметр семени, который вы могли бы использовать для этого. Если вы передадите последнее сгенерированное случайное значение в качестве семени для следующего вызова rand (), вам гарантировано получить новое случайное число.

Благодаря gbn для указания, что семя является целым числом, а rand () возвращает float. С этими знаниями, вот рабочий пример! Сначала создайте таблицу:

 create table RandomNumber (number float) insert into RandomNumber values (rand()) 

Затем возьмите случайное число и сохраните новый номер в транзакции:

 declare @new float begin transaction select @new = rand(-2147483648 + 4294967295 * number) from RandomNumber with (updlock, holdlock) update RandomNumber set number = @new commit transaction print 'Next bingo number is: ' + cast(cast(@new*100 as int) as varchar) 

Целое число SQL Server варьируется от -2147483648 до 2147483647, а случайное число – с плавающей точкой от 0.0 до 1.0. Таким образом, номер -2147483648 + 4294967295 * number должен охватывать весь диапазон доступных целых чисел.

Транзакция гарантирует, что только одно соединение за раз считывает и сохраняет новый номер. Таким образом, цифры являются случайными даже при разных подключениях к SQL Server. (Кстати, я голосовал за ответ gbn, кажется намного проще).

  • Выберите случайным образом и отсортируйте записи
  • Эффективно рандомизировать (перетасовывать) данные в таблице Sql Server
  • выберите случайное количество строк в sql-сервере
  • Где официальная документация для T-SQL «ORDER BY RAND ()» и «ORDER BY NEWID ()»?
  • Выберите N случайных строк с использованием свободного NHibernate
  • Значение по умолчанию для случайных 10 символов для столбца SQL Server
  • T-SQL со случайным возвратом нескольких строк, где ожидается
  • Случайные строки SQL Server в разделе where
  • Получать случайное количество строк из таблицы SQL Server
  • Использование тактовых импульсов в качестве случайных чисел
  • T-SQL sum () из rand (контрольная сумма (newid ()) не является случайной, если она появляется несколько раз в списке выбора?
  • Interesting Posts

    Является простым сайтом ASP.NET с использованием SQL Server, известного как 2-уровневая архитектура?

    Атака XSS на веб-сайт ASP.NET

    Вызовите хранимую процедуру из другого сохраненного proc ** без ** nesting

    Entity Framework 6 – Запросы синхронизации

    Mass Alter Сохраненная процедура для включения новой строки кода

    Большие вставки SQL вставки TVF и BULK

    SQL Update Left Join – но если ни одна запись не помещает 0 в поле

    Как изменить тип данных столбца, содержащего данные на сервере sql?

    Получить ранг пользователя, использующего SQL

    найти круговые транзакции в таблице базы данных

    Наиболее эффективное (пространство для хранения) способ хранения гистограмм в SQL

    SQL-фильтрация с помощью COALESCE или функции окна

    Источник данных отчета SSRS для запроса с несколькими базами данных

    Сделать скрытый столбец таблицы не занимать места в SSRS 2008 R2

    Легкий плагин или процедура для sqlserver Management Studio для вставки строк строки

    Давайте будем гением компьютера.