与 JOIN 混合使用时,UPDATE 的作用域规则是什么?

What are the scoping rules for UPDATE when mixed with a JOIN?

每当我读到如何使用 JOINUPDATE 和 table 时,别名的使用总是让我有点不适应。例如,从 here

中获取此代码
UPDATE ud
SET assid = s.assid
FROM ud u
JOIN sale s ON u.id=s.id

我很清楚 assid 来自第 1 行的 ud table。我不清楚的是为什么 ud 需要别名出现在第 3 行和第 4 行。这不是孤立事件。例如,同一页面上的另一个答案是

update u
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid

它在很多地方使用别名 u

这给了我一个问题:当您尝试使用 JOINUPDATE 时,您 do/don 不需要别名的规则究竟是什么?直接引用任何相关文档将不胜感激,但不是必需的。

从技术上讲,您不需要在列引用上使用别名前缀:

  • SET 的 left-hand 一侧,因为从逻辑上讲,该列不可能来自任何其他 table
  • 如果没有需要消除歧义的列名冲突(并且您肯定知道您永远不会将列添加到 可能 成为的任何相关 table冲突)

恕我直言,您不必担心任何关于何时可以使用 not 前缀的“规则”,而只需始终引用列所属的别名即可。为什么不总是清晰明了?

如果您正在寻找“官方”规则,我认为您会倒霉。在 this doc 中找不到关于此的任何内容,尽管第一个示例有这个,恕我直言,这有点过分(并且不使用别名):

UPDATE dbo.Table2   
SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB  
FROM dbo.Table2   
    INNER JOIN dbo.Table1   
    ON (dbo.Table2.ColA = dbo.Table1.ColA);  

在此站点上,许多 long-standing 规范示例在所有列引用中都是完全明确的,例如this one.

请注意,如果您使用 CTE 而不是 UPDATE ... FROM,则其中的 none 是神秘的,例如从 SELECT 开始,即 returns 您要更新的行

  select u.id, u.assid, s.assid new_assid 
  FROM ud u
  JOIN sale s ON u.id=s.id

。检查并验证数据,然后将其包装在 CTE 中并更新它

with q as
(
  select u.id, u.assid, s.assid new_assid 
  FROM ud u
  JOIN sale s ON u.id=s.id
)
update q set assid = new_assid

The documentation 特别指出:

FROM <table_source>

... snip ...

If the object being updated is the same as the object in the FROM clause and there is only one reference to the object in the FROM clause, an object alias may or may not be specified. If the object being updated appears more than one time in the FROM clause, one, and only one, reference to the object must not specify a table alias. All other references to the object in the FROM clause must include an object alias.

没有为任何table指定别名。如果不这样做,那么 table 显然只能指定一次。

但是,如果您确实提供了别名,那么这取决于:如果 table 在查询中存在一次,那么使用或不使用别名都可以。否则你必须使用别名。

说实话,,帮自己和大家一个忙,总是在每个 table,并在 UPDATE alias SET 部分指定别名。

同样,您应该始终为联接或表达式中的每个列引用使用 table 别名。这与您在 SELECT.

中应该做的一样

但是,我认为有必要在分配给的 left-hand-side 列上使用它,因为这些只能来自单个 table/view/alias:直接跟在关键字UPDATE之后的那个,所以加table别名只是废话。
在 SQL 方言中,例如 MySQL 允许这样做,那么您应该指定 table 别名,即使在 left-hand-side.

column_name

Is a column that contains the data to be changed. column_name must exist in table_or view_name.

所以推荐的声明如下所示:

UPDATE u     -- use the alias mentioned below
SET
  assid = s.assid    -- lh-side doesn't need alias, right-side does
FROM ud u    -- alias all tables
JOIN sale s ON u.id = s.id    -- add table aliases to all columns in joins