使用Join Duplicates更新语句

时间:2018-05-22 07:08:52

标签: sql sql-server

使用INNER JOIN执行更新导致目标表中的记录重复时,有关将结果表的哪些行作为要应用于更新的记录的规则是什么?

例如:

T1:

|-------------|-------------|
|     col1    |     col2    |
|-------------|-------------|
|       1     |       A     |
|-------------|-------------|
|       1     |       B     |
|-------------|-------------|
|       1     |       C     |
|-------------|-------------|

T2:

|-------------|-------------|
|     col1    |     col2    |
|-------------|-------------|
|       1     |       D     |
|-------------|-------------|
|       1     |       E     |
|-------------|-------------|
|       1     |       F     |
|-------------|-------------|

执行以下功能会导致表1的col2中的所有3行设置为D.

UPDATE T1
SET col2 = T2.col2
FROM #TEMP T1 INNER JOIN #TEMP2 T2 ON T2.col1 = T2.col1

下面的代码说明了这个例子:

SELECT 1 AS col1,'A' as col2 INTO #TEMP
INSERT INTO #TEMP
SELECT 1, 'B'
INSERT INTO #TEMP
SELECT 1, 'C'

SELECT 1 AS col1,'D' as col2 INTO #TEMP2
INSERT INTO #TEMP2
SELECT 1, 'E'
INSERT INTO #TEMP2
SELECT 1, 'F'

--SELECT * FROM #TEMP T1 INNER JOIN #TEMP2 T2 ON T2.col1 = T2.col1
--Result of below join

UPDATE T1
SET col2 = T2.col2
FROM #TEMP T1 INNER JOIN #TEMP2 T2 ON T2.col1 = T2.col1

SELECT * FROM #TEMP

为什么#TEMP的col2取值D?为什么不E或F? 这是因为它是连接中的第一个记录吗?

由于

1 个答案:

答案 0 :(得分:0)

我认为documentation在这个问题上非常明确。我加粗了最重要的部分:

  

指定FROM子句以提供条件时要小心   用于更新操作。 UPDATE语句的结果是   如果语句包含不是的FROM子句,则为undefined   以这样的方式指定,每个只有一个值可用   已更新的列出现,即UPDATE语句是否为   不确定。例如,在UPDATE语句中   在下面的脚本中,Table1中的两行都符合该资格   UPDATE语句中的FROM子句;但它未定义哪一行   来自Table1用于更新表2中的行。

换句话说,使用来自任意匹配行的值。关于哪一个没有规则。

设置特定值的便捷方法是使用apply

UPDATE T1
    SET col2 = T2.col2
    FROM #TEMP T1 CROSS APPLY
         (SELECT TOP (1) t2.*
          FROM #TEMP2 T2 
          WHERE T2.col1 = T2.col1
          ORDER BY ?  -- this ordering specifies the prioritization for the assignment
         ) T2;

ORDER BY指定要使用的行。