我必须用一个由3个表的联接返回的值来更新一个字段。

示例:

select
    im.itemid
    ,im.sku as iSku
    ,gm.SKU as GSKU
    ,mm.ManufacturerId as ManuId
    ,mm.ManufacturerName
    ,im.mf_item_number
    ,mm.ManufacturerID
from 
    item_master im, group_master gm, Manufacturer_Master mm 
where
    im.mf_item_number like 'STA%'
    and im.sku=gm.sku
    and gm.ManufacturerID = mm.ManufacturerID
    and gm.manufacturerID=34


我想更新表mf_item_numberitem_master字段值与在上述条件下连接的其他值。

如何在MS SQL Server中执行此操作?

评论

首先,请停止使用那些隐含的联接。这是一项糟糕的技术,由于意外的交叉连接而导致错误的结果。该代码样式已过期18年

另请参阅问题...stackoverflow.com/questions/1293330/…

#1 楼

UPDATE im
SET mf_item_number = gm.SKU --etc
FROM item_master im
JOIN group_master gm
    ON im.sku = gm.sku 
JOIN Manufacturer_Master mm
    ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
      gm.manufacturerID = 34

为了清楚起见... UPDATE子句可以引用FROM子句中指定的表别名。因此,在这种情况下,im是有效的
一般示例
UPDATE A
SET foo = B.bar
FROM TableA A
JOIN TableB B
    ON A.col1 = B.colx
WHERE ...


评论


Postgres抱怨UPDATE im。 im是Postgres无法识别的别名:/

– fatuhoku
16年10月10日在15:57

仅供参考,这不适用于MySQL(不同的语法)!对于MySQL,请查看gcbenison的答案

– Sliq
17年1月17日在16:28



#2 楼

最简单的方法之一是使用公用表表达式(因为您已经在SQL 2005中使用):

with cte as (
select
    im.itemid
    ,im.sku as iSku
    ,gm.SKU as GSKU
    ,mm.ManufacturerId as ManuId
    ,mm.ManufacturerName
    ,im.mf_item_number
    ,mm.ManufacturerID
    , <your other field>
from 
    item_master im, group_master gm, Manufacturer_Master mm 
where
    im.mf_item_number like 'STA%'
    and im.sku=gm.sku
    and gm.ManufacturerID = mm.ManufacturerID
    and gm.manufacturerID=34)
update cte set mf_item_number = <your other field>


查询执行引擎将自行计算如何更新记录。

评论


太好了,使用CTE使将原始SELECT转换为UPDATE变得简单

– SteveC
2013年6月14日14:48在

只要您的SELECT查询没有任何聚合,DISTINCT等,它就可以工作。

–保达
15年5月20日在23:41

我通常以分号开头以终止先前的语句(如果有)。 CTE令人rocks舌!设计简单,复杂的查询/合并更新。我用它所有的时间...

–亚当W
2015年12月17日下午5:19



#3 楼

使其适应MySQL-FROM中没有UPDATE子句,但这可行:

UPDATE
    item_master im
    JOIN
    group_master gm ON im.sku=gm.sku 
    JOIN
    Manufacturer_Master mm ON gm.ManufacturerID=mm.ManufacturerID
SET
    im.mf_item_number = gm.SKU --etc
WHERE
    im.mf_item_number like 'STA%'
    AND
    gm.manufacturerID=34


#4 楼

上面没有使用您的sql,但这是基于join语句更新表的示例。

UPDATE p
SET    p.category = c.category
FROM   products p
       INNER JOIN prodductcatagories pg
            ON  p.productid = pg.productid
       INNER JOIN categories c
            ON  pg.categoryid = c.cateogryid
WHERE  c.categories LIKE 'whole%'


#5 楼

您可以在UPDATE语句中指定用于确定如何以及通过“ FROM”子句进行更新的其他表,如下所示:

update item_master
set mf_item_number = (some value)
from 
   group_master as gm
   join Manufacturar_Master as mm ON ........
where
 .... (your conditions here)


在WHERE子句中,您可以需要提供条件和联接操作以将这些表绑定在一起。

Marc

评论


..或在FROM子句中使用ANSI JOINS

– gbn
09年11月11日在18:59

是的,请使用ansi联接,如果不小心出现交叉联接,可能会在更新中遇到真正的麻烦。

–HLGEM
09年6月11日在19:01

#6 楼

MySQL:通常,请根据您的要求进行必要的更改:

UPDATE
    shopping_cart sc
    LEFT JOIN
    package pc ON sc. package_id = pc.id    
SET
    sc. amount = pc.amount


#7 楼

像这样尝试...

Update t1.Column1 = value 
from tbltemp as t1 
inner join tblUser as t2 on t2.ID = t1.UserID 
where t1.[column1]=value and t2.[Column1] = value;


评论


这甚至在语法上都不是正确的,而更老的公认答案不仅在语法上是正确的,而且可以解决所问的确切问题。

–澳大利亚
9月3日16:16

#8 楼

您可以使用以下查询:

 UPDATE im
SET mf_item_number = (some value) 
FROM item_master im
JOIN group_master gm
    ON im.sku = gm.sku 
JOIN Manufacturer_Master mm
    ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
      gm.manufacturerID = 34    `sql`
 


#9 楼

您可以使用MERGE命令进行更新,从而对MATCHEDNOT MATCHED进行更多控制:(我稍微更改了源代码以说明我的观点)

USE tempdb;
GO
IF(OBJECT_ID('target') > 0)DROP TABLE dbo.target
IF(OBJECT_ID('source') > 0)DROP TABLE dbo.source
CREATE TABLE dbo.Target
    (
      EmployeeID INT ,
      EmployeeName VARCHAR(100) ,
      CONSTRAINT Target_PK PRIMARY KEY ( EmployeeID )
    );
CREATE TABLE dbo.Source
    (
      EmployeeID INT ,
      EmployeeName VARCHAR(100) ,
      CONSTRAINT Source_PK PRIMARY KEY ( EmployeeID )
    );
GO
INSERT  dbo.Target
        ( EmployeeID, EmployeeName )
VALUES  ( 100, 'Mary' );
INSERT  dbo.Target
        ( EmployeeID, EmployeeName )
VALUES  ( 101, 'Sara' );
INSERT  dbo.Target
        ( EmployeeID, EmployeeName )
VALUES  ( 102, 'Stefano' );

GO
INSERT  dbo.Source
        ( EmployeeID, EmployeeName )
VALUES  ( 100, 'Bob' );
INSERT  dbo.Source
        ( EmployeeID, EmployeeName )
VALUES  ( 104, 'Steve' );
GO

SELECT * FROM dbo.Source
SELECT * FROM dbo.Target

MERGE Target AS T
USING Source AS S
ON ( T.EmployeeID = S.EmployeeID )
WHEN MATCHED THEN
    UPDATE SET T.EmployeeName = S.EmployeeName + '[Updated]';
GO 
SELECT '-------After Merge----------'
SELECT * FROM dbo.Source
SELECT * FROM dbo.Target


评论


不,我很确定,在SQL Server 2005中,这是问题的标记方式,但这是现代SQL Server版本上的最佳方法(即,更标准的方法)

–澳大利亚
9月3日16:17

#10 楼

使用SQL中的联接查询进行更新非常简单。您可以不使用FROM子句来进行更新。这是一个示例:
    UPDATE customer_table c 

      JOIN  
          employee_table e
          ON c.city_id = e.city_id  
      JOIN 
          anyother_ table a
          ON a.someID = e.someID

    SET c.active = "Yes"

    WHERE c.city = "New york";


#11 楼

让我向所有现有答案添加警告:
在使用SELECT ... FROM语法时,应记住,它是T-SQL的专有语法,并且是不确定的。最糟糕的部分是,您不会收到任何警告或错误,它会顺利执行。
示例中的完整解释在文档中:

在指定FROM子句以提供条件时请谨慎使用用于更新操作。如果该语句包括未指定的FROM子句,则UPDATE语句的结果是未定义的,即对于更新的每一列事件,只有一个值可用,也就是说,如果UPDATE语句不是确定性的。 >