在SQL服务器中使用JOIN更新表?

我想更新表中的一列,在其他表上进行连接,例如:

UPDATE table1 aINNER JOIN table2 b ON a.commonfield = b.[common field]SET a.CalculatedColumn= b.[Calculated Column]WHEREb.[common field]= a.commonfieldAND a.BatchNO = '110'

但它在抱怨:

Msg 170, Level 15, State 1, Line 2
第2行:“a”附近的语法不正确。

这里有什么不对?

1063837 次浏览

尝试:

UPDATE table1SET CalculatedColumn = ( SELECT [Calculated Column]FROM table2WHERE table1.commonfield = [common field])WHERE  BatchNO = '110'

试试这样:

    UPDATE aSET a.CalculatedColumn= b.[Calculated Column]FROM table1 a INNER JOIN table2 b ON a.commonfield = b.[common field]WHERE a.BatchNO = '110'

您不太SQLServer专有的UPDATE FROM语法。也不确定为什么您需要加入CommonField并在之后对其进行过滤。试试这个:

UPDATE t1SET t1.CalculatedColumn = t2.[Calculated Column]FROM dbo.Table1 AS t1INNER JOIN dbo.Table2 AS t2ON t1.CommonField = t2.[Common Field]WHERE t1.BatchNo = '110';

如果您正在做一些愚蠢的事情-例如不断尝试将一列的值设置为另一列的聚合(这违反了避免存储冗余数据的原则),您可以使用CTE(公共表表达式)-请参阅这里这里了解更多详细信息:

;WITH t2 AS(SELECT [key], CalculatedColumn = SUM(some_column)FROM dbo.table2GROUP BY [key])UPDATE t1SET t1.CalculatedColumn = t2.CalculatedColumnFROM dbo.table1 AS t1INNER JOIN t2ON t1.[key] = t2.[key];

这很愚蠢的原因是,每次table2中的任何一行发生变化时,您都必须重新运行整个更新。SUM是您始终可以在运行时计算的东西,这样做,永远不必担心结果过时。

我发现在更新之前将UPDATE转换为SELECT以获取我想要更新的行作为测试很有用。如果我可以选择我想要的确切行,我可以只更新我想要更新的行。

DECLARE @expense_report_id AS INTSET @expense_report_id = 1027
--UPDATE expense_report_detail_distribution--SET service_bill_id = 9
SELECT *FROM expense_report_detail_distribution erddINNER JOIN expense_report_detail erdINNER JOIN expense_report erON er.expense_report_id = erd.expense_report_idON erdd.expense_report_detail_id = erd.expense_report_detail_idWHERE er.expense_report_id = @expense_report_id

亚伦给出的答案是完美的:

UPDATE aSET a.CalculatedColumn = b.[Calculated Column]FROM Table1 AS aINNER JOIN Table2 AS bON a.CommonField = b.[Common Field]WHERE a.BatchNo = '110';

只是想添加为什么这个问题发生在SQL服务器当我们尝试使用一个表的别名,而更新该表,下面提到的语法将始终给出错误:

update tableName tset t.name = 'books new'where t.id = 1

如果您正在更新单个表或在使用连接时进行更新,则case可以是任何。

虽然上述查询在PL/SQL中可以正常工作,但在SQLServer中不行。

在SQLServer中使用表别名更新表的正确方法是:

update tset t.name = 'books new'from tableName twhere t.id = 1

希望它能帮助大家为什么错误来到这里。

另一种方法是使用合并

  ;WITH cteTable1(CalculatedColumn, CommonField)AS(select CalculatedColumn, CommonField from Table1 Where BatchNo = '110')MERGE cteTable1 AS targetUSING (select "Calculated Column", "Common Field" FROM dbo.Table2) AS source ("Calculated Column", "Common Field")ON (target.CommonField = source."Common Field")WHEN MATCHED THENUPDATE SET target.CalculatedColumn = source."Calculated Column";

合并是SQL标准的一部分

-我也很确定内连接更新是不确定的。类似的问题,答案是这样说的http://ask.sqlservercentral.com/questions/19089/updating-two-tables-using-single-query.html

似乎SQLServer 2012也可以处理Teradata的旧更新语法:

UPDATE aSET a.CalculatedColumn= b.[Calculated Column]FROM table1 a, table2 bWHEREb.[common field]= a.commonfieldAND a.BatchNO = '110'

如果我没记错的话,当我尝试类似的查询时,2008R2给出了错误。

    UPDATE mytableSET myfield = CASE other_fieldWHEN 1 THEN 'value'WHEN 2 THEN 'value'WHEN 3 THEN 'value'ENDFrom mytableJoin otherTable on otherTable.id = mytable.idWhere othertable.somecolumn = '1234'

更多选择这里

MERGE table1 TUSING table2 SON T.CommonField = S."Common Field"AND T.BatchNo = '110'WHEN MATCHED THENUPDATESET CalculatedColumn = S."Calculated Column";

我有同样的问题…你不需要添加一个物理列…因为现在你将不得不维护它…您可以做的是在选择查询中添加一个泛型列:

EX:

select tb1.col1, tb1.col2, tb1.col3 ,(select 'Match' from table2 as tbl2where tbl1.col1 = tbl2.col1 and tab1.col2 = tbl2.col2)from myTable as tbl1

Aaron上面的方法非常适合我。我的更新语句略有不同,因为我需要基于一个表中连接的两个字段进行连接,以匹配另一个表中的字段。

 --update clients table cell field from custom table containing mobile numbers
update clientsset cell = m.Phonefrom clients as cinner join [dbo].[COSStaffMobileNumbers] as mon c.Last_Name + c.First_Name = m.Name

我想,这就是你要找的。

UPDATETable1SETTable1.columeName =T1.columeName * T2.columeNameFROMTable1 T1INNER JOIN Table2 T2ON T1.columeName = T2.columeName;

使用MYSQL的人

UPDATE table1 INNER JOIN table2 ON table2.id = table1.id SET table1.status = 0 WHERE table1.column = 20