如何在SQL Server上使用多个JOIN更新表格?(来自FROM FROM JOIN)

5

如何在SQL Server上用多个Joins更新表?在MySQL中,您可以为更新的表定义别名,但是在TSQL中如何实现呢?

 UPDATE recert.ou              --#1-- In MSSQL/TSQL no alias allowed
SET parent_id = o2.ID
    FROM recert.ou as O              
    JOIN recert.country C ON C.ID = O.country_id
    JOIN recert.ou P ON O.parent_id = P.ID and p.country_id <> O.country_id     
    JOIN recert.ou o2 on o2.name = p.name and c.ID = o2.country_id              
    JOIN recert.country as c2 on c2.ID = o2.country_id
           WHERE O.ID = o2.ID

-

RESULT: *The table 'o' is ambiguous.*

1
你为什么要将 o 别名为 o - Nikola Markovinović
2
如果你有UPDATE O1 SET parent_id = O2.ID FROM o AS O1 blah blah blah...会发生什么?TSQL允许在UPDATE语句中出现别名。但我以前从未尝试过将表的别名设置为其自身的名称。 - MatBailie
@NikolaMarkovinović:原文:FROM recert.o AS o - hoerf
SQL Server 的哪个版本?我刚刚检查了 2005 版本,是的,你可以在更新语句中使用别名。 - Nikola Markovinović
SQL Server 2008 R2: Msg 8154, Level 16, State 1, Line 2 The table 'recert.o' is ambiguous. 这是因为JOIN recert.o PJOIN recert.o o2引起的。 - hoerf
@NikolaMarkovinović:由于他使用相同的表别名进行连接,将会出现错误。在同一张表上进行内部连接将抛出模糊表错误。如果您不是与正在查询中更新的相同表进行连接,则可以在更新语句中使用别名。 - praveen
4个回答

9

这个在 Sql Fiddle 上可以运行.

UPDATE o
SET parent_id = o2.ID
    FROM recert O
    JOIN c C ON C.ID = O.country_id
    JOIN recert P ON O.parent_id = P.ID and p.country_id <> O.country_id
    JOIN recert o2 on o2.name = p.name and c.ID = o2.country_id
    JOIN c c2 on c2.ID = o2.country_id
WHERE O.ID = o2.ID

我猜测问题出在您试图重新对别名进行别名处理,但我不确定。


recert 是模式,表名为 ou。-> recert.ou as o。我编辑了问题。 - hoerf
@hoerf - 把这个看作是一个概念验证。只需在上面的查询中的每个recert后面添加.ou即可。 - Nikola Markovinović
@hoerf,根据您目前的查询,将“update recert.ou”替换为“update o”。 - Nikola Markovinović
把下面关于编程的内容从英语翻译成中文。返回已翻译的文本。 - hoerf
@hoerf 的意思是在更新中使用别名,而你正在使用表名。 - Nikola Markovinović

1

您可以将所有内容移至 WHERE 子句中:

UPDATE o              --#1-- In MSSQL/TSQL no alias allowed
    SET parent_id = o2.ID
    FROM c, o, o o2, C c2
    Where o.country_id = c.id and o.parent_id = p.id and p.country_id <> O.country_id and
          o2.name = p.name and c.ID = o2.country_id and c2.ID = o2.country_id

这不是我最喜欢的连接方式,但对于您的目的来说应该足够了。

然而,在TSQL中,我会真正执行以下操作。创建一个查询,返回每个ID的新更新值。然后编写以下格式的查询:

with toupdate as (<the query>)
    update o
        set o.parent_id = toupdate.id
    from toupdate
    where o.id = toupdate.id       

相同错误 UPDATE recert.ou SET parent_id = o2.[ID] FROM recert.ou AS O, recert.country, recert.ou AS P, recert.ou as o2, recert.country c2, recert.country c WHERE O.ID = o2.ID AND C.ID = O.country_id AND O.parent_id = P.ID and p.country_id <> O.country_id AND o2.name = p.name and c.ID = o2.country_id AND c2.ID = o2.country_id - hoerf

1

您只需要删除o表的别名即可。

UPDATE o              
SET parent_id = o2.ID
FROM o               
JOIN c C ON C.ID = o.country_id
JOIN o P ON o.parent_id = P.ID and p.country_id <> o.country_id   
JOIN o o2 on o2.name = p.name and c.ID = o2.country_id             
JOIN c c2 on c2.ID = o2.country_id
 WHERE o.ID = o2.ID

我在 JOIN ... o.country_id 中使用 o 作为别名,其中 FROM recert.o AS O 中的 O 是指别名。 - hoerf

-2
自连接更新
update #table1 set column1= b.column2
from #table1 #table1, #table1 b where #table1.Id=b.Id  

用实际的表名替换#table1,用实际的列名替换column1和column2。 - Prakash Belalakatte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接