我怎样才能插入随机值到一个SQL Server表?(How can I insert random

2019-07-19 05:16发布

我试图插入随机从预先定义的值列表值转换成用于测试的表。 我尝试使用这个StackOverflow的问题找到了解决办法:

stackoverflow.com/.../update-sql-table-with-random-value-from-other-table

当我试过了这一点,我所有的“随机”的价值观正在插入的是完全对所有3000条记录是相同的。

当我运行,实际上选择随机行查询的一部分,但它选择一个随机记录每次我用手运行它的时候,所以我知道的查询工作。 我最好的猜测所发生的事情是:

  • SQL Server在优化SELECT不知何故,不允许子查询进行评估不止一次
  • 随机值的种子在每个记录相同的查询更新

我卡在什么我的选择是。 我做得不对,或者是有另一种方式我应该这样做呢?

这是我使用的代码:

DECLARE @randomStuff TABLE ([id] INT, [val] VARCHAR(100))

INSERT INTO @randomStuff ([id], [val]) 
VALUES ( 1,  'Test Value 1' )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 2,  'Test Value 2' )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 3,  'Test Value 3' )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 4,  'Test Value 4' )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 5,  'Test Value 5' )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 6,  null )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 7,  null )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 8,  null )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 9,  null )
INSERT INTO @randomStuff ([id], [val])
VALUES ( 10, null )

UPDATE MyTable
SET MyColumn = (SELECT TOP 1 [val] FROM @randomStuff ORDER BY NEWID())

Answer 1:

当查询引擎看到这个...

(SELECT TOP 1 [val] FROM @randomStuff ORDER BY NEWID())

......这一切都喜欢,“OOOOH,一个超高速缓存标量子查询,我要缓存!”

你需要欺骗查询引擎误以为它是不可缓存的。 jfar的答案很接近,但查询引擎很聪明,看到的tautalogy MyTable.MyColumn = MyTable.MyColumn ,但它不是足够聪明,通过这个看到。

UPDATE MyTable
   SET MyColumn = (SELECT TOP 1 val
                     FROM @randomStuff r
                          INNER JOIN MyTable _MT
                                  ON M.Id = _MT.Id
                    ORDER BY NEWID())
 FROM MyTable M

通过引入外部表(MT)到子查询中,查询引擎假设子查询将需要重新评估。 任何真正的工作,但我MyTable.Id的(假设的)主键去,因为它会被编入索引,并会增加非常小的开销。

游标可能会是一样快,但肯定是没有的乐趣。



Answer 2:

使用交叉连接,生成随机数据



Answer 3:

我已经受够了这个戏,并发现了一个相当哈克的方式与使用中间表变量来做到这一点。

一旦@randomStuff设置,我们这样做(注意我的情况,@MyTable是表变量,相应地调整你的正常的表):

DECLARE @randomMappings TABLE (id INT, val VARCHAR(100), sorter UNIQUEIDENTIFIER)

INSERT INTO @randomMappings 
SELECT M.id, val, NEWID() AS sort 
FROM @MyTable AS M 
CROSS JOIN @randomstuff

所以在这一点,我们有与(mytable的ID,随机值)的每一种组合的中间表,以及用于特定于该组合的每一行的随机排序值。 然后

DELETE others FROM @randomMappings AS others 
INNER JOIN @randomMappings AS lower 
ON (lower.id = others.id) AND (lower.sorter < others.sorter)

这是一个老把戏其删除除了具有较低排序值对于一个给定MyTable.id所有行 - 加入表本身,其中值较小,并删除任何地方这样的联接成功。 这只是留下的最低值。 因此,对于每个MyTable.id,我们只需要留下一个(随机)值。然后,我们只需将其回表:

UPDATE @MyTable
SET MyColumn = random.val
FROM @MyTable m, @randomMappings AS random
WHERE (random.id = m.id)

就大功告成了!

说,这是哈克...



Answer 4:

我现在没有时间来检查这个权利,但我的直觉告诉我,如果你要在服务器上创建一个函数来获取随机值,它不会优化它。

那么你将有

UPDATE MyTable
Set MyColumn = dbo.RANDOM_VALUE()


Answer 5:

有没有优化怎么回事。

您的使用选择单个值的子查询,有什么优化。

您也可以尝试把一列从表的更新中选择,看看有没有改变任何东西。 这可能触发评估为MyTable的每一行

UPDATE MyTable
SET MyColumn = (SELECT TOP 1 [val] FROM @randomStuff ORDER BY NEWID()
    WHERE MyTable.MyColumn = MyTable.MyColumn )


Answer 6:

我想出了一个解决方案,它是一个黑客位和效率非常低(10〜秒更新3000条记录)。 因为这是被用来生成测试数据,我就不必关心速度但是。

在这个解决方案,我遍历表中的每一行,同时更新值一行。 看来工作:

DECLARE @rows INT 
DECLARE @currentRow INT

SELECT @rows = COUNT(*) FROM dbo.MyTable
SET @currentRow = 1

WHILE @currentRow < @rows
BEGIN 

UPDATE MyTable
SET MyColumn = (SELECT TOP 1 [val] FROM @randomStuff ORDER BY NEWID())
WHERE MyPrimaryKey = (SELECT b.MyPrimaryKey
 FROM(SELECT a.MyPrimaryKey, ROW_NUMBER() OVER (ORDER BY MyPrimaryKey) AS rownumber
      FROM MyTable a) AS b
 WHERE @currentRow = b.rownumber
)

SET @currentRow = @currentRow + 1
END 


文章来源: How can I insert random values into a SQL Server table?