简单的更新语句,以便为所有行分配不同的值

时间:2012-10-16 19:36:43

标签: sql sql-server

我正在尝试将一个表中的列设置为随机外键以进行测试。 我尝试使用以下查询

update table1 set table2Id = (select top 1 table2Id from table2 order by NEWID())

这将随机获得一个table2Id,并将其作为table1中的外键分配给每一行。 这几乎就是我想要的,但我希望每一行都能获得不同的table2Id值。

我可以通过遍历table1中的行来完成此操作,但我知道有一种更简洁的方法。

4 个答案:

答案 0 :(得分:8)

在某些测试表上,我的结束原始计划如下所示。

Original Plan

它只计算一次结果并将其缓存在sppol中然后重放该结果。您可以尝试以下操作,以便SQL Server将子查询视为相关的,并且需要为每个外行重新评估。

UPDATE table1
SET    table2Id = (SELECT TOP 1 table2Id
                   FROM   table2
                   ORDER  BY Newid(),
                             table1.table1Id)

对我来说,这个计划没有假脱机。

New Plan

重要的是关联来自table1的唯一字段,但是即使添加了一个假脱机,它也必须始终被反弹而不是重绕(重放最后的结果),因为每个字段的相关值都不同行。

如果表格很大,这将会很慢,因为所需的工作是两个表格行的乘积(对于table1中的每一行,它需要对table2进行全面扫描

答案 1 :(得分:2)

我还有另外一个回答这个问题,因为我的第一个回答是不完整的。

由于在分配table2_id之前没有其他方法可以加入这两个表,因此您可以使用row_numbertable1table2提供临时密钥。

with
 t1 as (
  select row_number() over (order by table1_id) as row, table1_id
  from table1 )
,
t2 as (
  select row_number() over (order by NEWID()) as row, table2_id 
  from table2 )

update table1
set table2_id = t2.table2_id
from t1 inner join t2
on t1.row = t2.row

select * from table1

SQL小提琴测试它:http://sqlfiddle.com/#!6/bf414/12

答案 2 :(得分:0)

打破并使用循环。这很有效,虽然速度很慢。

Select *
Into   #Temp
From   table1

Declare @Id int

While (Select Count(*) From #Temp) > 0
Begin

    Select Top 1 @Id = table1Id From #Temp

    update table1 set table2Id = (select top 1 table2Id from table2 order by NEWID()) where table1Id = @Id

    Delete #Temp Where table1Id = @Id

End
drop table #Temp

答案 3 :(得分:-1)

我将假设MS SQL基于前1:

update table1 
set table2Id = 
  (select top 1 table2Id from table2 tablesample(1 percent))

(抱歉,未经测试)