Это даст вам 1000 строк данных для вставки.
DECLARE @D1 DATE = '19500101'
DECLARE @D2 DATE = '19991231'
;WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT TOP 1000
DATEADD(DAY,ABS(CHECKSUM(NEWID())) % (1+DATEDIFF(DAY,@D1,@D2)),@D1)
FROM cteTally
Примечание: этот ответ первоначально использовал ABS(CAST(CRYPT_GEN_RANDOM(4) AS INT))
для генерации случайных чисел.В отличие от RAND()
, который оценивается только один раз для каждого оператора, он оценивается один раз для каждой строки, поэтому будет работать.
Однако кажется, что Оптимизатор запросов не осознает этого и рассматривает его как константу.Для генерации случайных данных это, вероятно, не будет иметь значения (если вы не заполняете столбец, ограниченный внешним ключом)
, но я только что протестировал альтернативу ABS(CHECKSUM(NEWID()))
, чтобы увидеть, было ли какое-либо преимущество в производительностиодин за другим.
Типичная скорость генерации 1 000 000 строк с использованием таблицы чисел, приведенной выше, и выбор значения MAX
(чтобы избежать затрат на возврат всех этих строк клиенту)
ABS(CAST(CRYPT_GEN_RANDOM(4) AS INT))
/*CPU time = 4180 ms, elapsed time = 4395 ms.*/
ABS(CHECKSUM(NEWID()))
/*CPU time = 953 ms, elapsed time = 1163 ms.*/
(SELECT 1) /*A constant value just to get a baseline*/
/*CPU time = 499 ms, elapsed time = 457 ms.*/
Так что, если вам не нужен криптографически безопасный PRNG, его, вероятно, лучше избегать!