sql - 使用连接重复更新语句
问题描述
当使用导致目标表中记录重复的 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?这仅仅是因为它是连接中的第一条记录吗?
谢谢
解决方案
我认为文档在这个问题上非常清楚。我将最重要的部分加粗:
指定 FROM 子句以提供更新操作的条件时要小心。 如果 UPDATE 语句包含未指定的 FROM 子句,则该语句的结果是未定义的,即,如果 UPDATE 语句不是确定性的,则每个更新的列出现只有一个值可用。例如,在下面脚本的 UPDATE 语句中,Table1 中的两行都满足 UPDATE 语句中 FROM 子句的条件;但未定义 Table1 中的哪一行用于更新 Table2 中的行。
换句话说,使用来自任意匹配行的值。没有关于哪一个的规则。
设置特定值的一种便捷方法是使用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
指定要使用的行。
推荐阅读
- html - 用 box-shadow 替换表单输入的轮廓是否违反任何 WCAG 准则?
- tcl - 没有全名的呼叫程序
- kubernetes - 自动向 OpenShift 中的服务帐户添加拉取机密
- debugging - 在 Visual Studio 2019 中以不同的解决方案启动多个项目
- powershell - Powershell 未正确解码 base64 命令
- pyspark - Py4JJavaError:调用 o8484.showString 时出错
- javascript - reactjs中的道具状态值
- mysql - 将 PostgreSQL 转换为 MySQL
- java - RecyclerView 在 Fragment 中不显示项目,但在 Activity 中有效
- sql - 使用备份和恢复功能将 Postgis 数据库从一个桌面迁移到另一个失败