Sql server 如果在FROM/JOIN子句中没有提到更新的表,UPDATE语句会发生什么情况?

Sql server 如果在FROM/JOIN子句中没有提到更新的表,UPDATE语句会发生什么情况?,sql-server,tsql,sql-update,Sql Server,Tsql,Sql Update,我打算在SQL Server数据库表上运行以下UPDATE语句: UPDATE TABLE_A SET COL_1=B.COL_1 FROM TABLE_A A INNER JOIN TABLE_B B ON A.KEY_1=B.KEY_1 WHERE B.COL_2 IS NOT NULL AND A.COL_1=91216599 我错误地运行了以下语句: UPDATE TABLE_A SET COL_1=B.COL_1 FROM TABLE_A_COPY A INNER JOIN

我打算在SQL Server数据库表上运行以下UPDATE语句:

UPDATE TABLE_A
SET COL_1=B.COL_1
FROM TABLE_A A
INNER JOIN TABLE_B B
   ON A.KEY_1=B.KEY_1
WHERE B.COL_2 IS NOT NULL
  AND A.COL_1=91216599
我错误地运行了以下语句:

UPDATE TABLE_A
SET COL_1=B.COL_1
FROM TABLE_A_COPY A
INNER JOIN TABLE_B B
   ON A.KEY_1=B.KEY_1
WHERE B.COL_2 is not NULL
  AND A.COL_1=91216599
请注意,在第二条错误语句中,FROM子句指定了table table_A_COPY而不是table_A。在执行任何更新之前,这两个表具有完全相同的模式,即相同的列和相同的数据

表A和表A副本都有大约1亿条记录,更新会影响大约50万条记录。第二条语句(错误的语句)运行数小时并失败,而第一条语句(正确的语句)运行40秒并成功

显然,这两条语句在语法上都是正确的,但我不确定我让SQLServer对第一条语句做了什么

我的问题是:

SQL Server在第二条语句中尝试执行什么操作?由于我的错误,我没有指定从表A到表A副本的记录之间的链接,所以它是否试图在两者之间进行交叉连接,然后更新表A中的每条记录数百万次

如果这不是一个太宽泛的问题,那么对于这样的UPDATE语句,在FROM/JOIN子句中没有提到要更新的表,什么样的场景才是有效的呢。为什么会有人这样做?为什么SQL Server会允许这样做


我确实尝试过搜索我的问题的答案,但谷歌似乎认为我是在问语法更新。

1表A和表A副本之间没有联系,所以你会得到交叉连接和大量更新同一行。如果涉及并行执行,则结果可能是不确定的:

在上面的代码中检查表\u是如何更改键为\u 1=6的记录的

二, SQL Server UPDATE FROM/DELETE FROM语法比ANSI标准要广泛得多,您遇到的问题可以减少为多次更新同一行。使用UPDATE,您不会收到任何错误或警告:

来自和:

正确吗?呸,谁在乎呢

嗯,大多数都是这样。这就是我们测试的原因

如果我在SELECT查询中弄乱了连接条件,导致太多行 从第二桌比赛开始,我一测试就会看到,因为我 获取比预期更多的行。如果我弄乱了子查询条件 在一个ANSI标准更新查询中,我以类似的方式看到了它 更快,因为如果子查询 返回多个值。但是有了来自 语法,我可以搞乱连接,但我永远不会注意到–SQL Server将 如果同一行与更多行匹配,则愉快地反复更新该行 联接表中的多行,仅包含最后一行的结果 这些更新仍然存在。没有办法知道那是哪一排 将是,因为这取决于发生的查询执行计划 被选中。最坏的情况是执行 在所有测试过程中,计划恰好会产生预期的结果 在单处理器开发服务器上–然后,在 部署到四路双核生产服务器,这是我们宝贵的 数据突然击中风扇

如果使用例如“合并”,则会出现错误,指示:

MERGE语句试图更新或删除同一行 不止一次。当目标行与多个源匹配时会发生这种情况 一行MERGE语句不能更新/删除目标的同一行 表多次。优化ON子句以确保目标行 最多匹配一个源行,或使用GROUPBY子句进行分组 源行

因此,您需要更加小心地检查代码。我也希望得到错误,但正如你们在连接链接中看到的,这不会发生

避免这种情况的一种方法是使用UPDATE alias,这样您就可以确保使用的表参与了“自联接”,而不涉及其他表:

UPDATE A
SET COL_1=B.COL_1
FROM #TABLE_A A
INNER JOIN #TABLE_B B
   ON A.KEY_1=B.KEY_1
WHERE B.COL_2 IS NOT NULL
  AND A.COL_1=91216599;

SQL将允许许多可能没有意义的东西 请注意,表格B位于屏幕的两侧

select *  
from tableA
join tableB 
  on tableB.col1 = tableB.col1
SQL只是检查语法——这取决于您,所以请编写一条有意义的语句

在某些情况下,您可能确实希望进行跨产品类型的更新

这就是我写这篇声明的方式 我把表格的名字排成一行,这样比较容易看

UPDATE TABLE_A
   SET A.COL_1 = B.COL_1
  FROM TABLE_A A
  JOIN TABLE_B B
        ON A.KEY_1 = B.KEY_1
       AND B.COL_2 IS NOT NULL
       AND A.COL_1 = 91216599 
       AND A.COL_1 <> B.COL_1

我猜你得到了表a的Cartesean积,以及表a和表B之间的连接。这当然可以解释为什么需要这么长时间…@Ricardo哪种说法是正确的?你的第一/第二个问题和不正确/正确的一个对我来说没有意义。你能编辑你的简历吗question@Ricardo阅读您的帖子**第一条语句不正确的语句**运行数小时并失败,而第二条语句正确的语句运行40秒并成功。@lad2025-正确!对不起,我把那句话中的两句话都弄混了。里卡多:对我来说,这是一个类似的例子,对我来说,最容易发现它的方法是t o在更新中使用别名,如:从表A更新集合COL_1=B.COL_1,从A.KEY_1=B.KEY_1上的内部联接表B更新集合COL_1=B.COL_1,其中B.COL_2不为空,A.COL_1=91216599;
UPDATE TABLE_A
   SET A.COL_1 = B.COL_1
  FROM TABLE_A A
  JOIN TABLE_B B
        ON A.KEY_1 = B.KEY_1
       AND B.COL_2 IS NOT NULL
       AND A.COL_1 = 91216599 
       AND A.COL_1 <> B.COL_1