在SQL Server中,可以使用INSERT.. SELECT语句将行插入表中:
INSERT INTO Table (col1, col2, col3)
SELECT col1, col2, col3 
FROM other_table 
WHERE sql = 'cool'

是否还可以使用SELECT更新表?我有一个包含这些值的临时表,并想使用这些值更新另一个表。也许是这样的:
UPDATE Table SET col1, col2
SELECT col1, col2 
FROM other_table 
WHERE sql = 'cool'
WHERE Table.id = other_table.id


#1 楼

UPDATE
    Table_A
SET
    Table_A.col1 = Table_B.col1,
    Table_A.col2 = Table_B.col2
FROM
    Some_Table AS Table_A
    INNER JOIN Other_Table AS Table_B
        ON Table_A.id = Table_B.id
WHERE
    Table_A.col3 = 'cool'


评论


如果要编辑表之间的链接(SET Table.other_table_id = @NewValue),则将ON语句更改为类似ON Table.id = @IdToEdit AND other_table.id = @NewValue

– Trisped
2012年10月24日18:41

@CharlesWood是的。我在MySQL中有同样的问题。如果有人知道如何将其实现到MySQL并与所有人共享,那就太好了。我确定很多人正在寻找MySQL版本解决方案

–罗杰·雷(Roger Ray)
13年11月27日在3:34

如何在集合中使用别名?从表a.id = b.id上的内部联接表2 b更新表集a.col1 = b.col2;相反,我必须使用表a.id = b.id上的内部联接table2 b的更新表集table.col1 = b.col2;

– ThinkCode
2014年1月20日23:08

有点相关,我经常喜欢先将UPDATE查询写为SELECT语句,以便可以在执行之前看到将要更新的数据。塞巴斯蒂安(Sebastian)在最近的博客文章中介绍了一种技术:sqlity.net/en/2867/update-from-select

–dennislloydjr
15年8月21日在19:48

您不能执行SET Table_A.col1 = SUM(Table_B.col1)或任何其他聚合。 Jamal的答案使您可以将聚合放入SELECT stackoverflow.com/a/8963158/695671

–Jason S
19年7月14日在22:31



#2 楼

在SQL Server 2008(或更高版本)中,使用MERGE

MERGE INTO YourTable T
   USING other_table S 
      ON T.id = S.id
         AND S.tsql = 'cool'
WHEN MATCHED THEN
   UPDATE 
      SET col1 = S.col1, 
          col2 = S.col2;


或者:

MERGE INTO YourTable T
   USING (
          SELECT id, col1, col2 
            FROM other_table 
           WHERE tsql = 'cool'
         ) S
      ON T.id = S.id
WHEN MATCHED THEN
   UPDATE 
      SET col1 = S.col1, 
          col2 = S.col2;


评论


MERGE也可以用于“ Upserting”记录;也就是说,如果存在匹配的记录,则更新;如果找不到匹配的记录,则插入新记录

–白蛋白
2012年5月15日19:51

对我来说,这比等效的update ... join语句快10倍。

– Paul Suart
2013年4月3日在2:49

MERGE也可以用于DELETE。但请小心MERGE,因为TARGET表不能是远程表。

–Möoz
13年8月8日,下午3:58

合并错误:mssqltips.com/sqlservertip/3074/…

–西蒙D
2014年8月27日9:38



@SimonD:选择任何SQL Server关键字,您将发现错误。你的意思是?我认为与UPDATE相关的错误(以及更基本的错误)要比MERGE多,人们刚刚学会与之共处,它们就成为景观的一部分(“功能”)。考虑一下,当UPDATE是新手时,博客就不存在了。

–有一天
2014年10月3日15:29



#3 楼

 UPDATE YourTable 
SET Col1 = OtherTable.Col1, 
    Col2 = OtherTable.Col2 
FROM (
    SELECT ID, Col1, Col2 
    FROM other_table) AS OtherTable
WHERE 
    OtherTable.ID = YourTable.ID
 


评论


到目前为止,最简单的!但是,您缺少内部SELECT的ID字段。您需要此文件才能使WHERE子句起作用

–约翰·多尔蒂(John Doherty)
2014年10月31日在18:03



这几乎可以在几乎所有DBMS上使用,这意味着一次学习,随处执行。如果这对您来说比性能更重要,那么您可能更喜欢此答案,尤其是如果您的更新是一次性更正某些数据的话。

–艾伦·麦克唐纳(Alan Macdonald)
16年2月1日在14:46

如果需要使用第二个表中的集合来设置第一个表,则可以将集合放入select子查询中,因为您无法执行SET Table_A.col1 = SUM(Table_B.col1)(或任何其他集合函数)。因此,比罗宾·戴(Robin Day)的答案要好。

–Jason S
19年7月14日在22:38

#4 楼

我将修改Robin对以下内容的出色答案:

UPDATE Table
SET Table.col1 = other_table.col1,
 Table.col2 = other_table.col2
FROM
    Table
INNER JOIN other_table ON Table.id = other_table.id
WHERE
    Table.col1 != other_table.col1
OR Table.col2 != other_table.col2
OR (
    other_table.col1 IS NOT NULL
    AND Table.col1 IS NULL
)
OR (
    other_table.col2 IS NOT NULL
    AND Table.col2 IS NULL
)


如果没有WHERE子句,您甚至会影响不需要受影响的行,这可能(可能)导致索引重新计算或触发触发器,这些触发触发器本来不应该触发的。

评论


假设所有列均不可为空。

–马丁·史密斯
2011年11月6日,0:03

没错,我是手动输入示例。我在where语句中添加了第三和第四子句来处理。

–抢劫犯
2011年11月11日20:27

存在的地方(SELECT T1.Col1,T1.Col2除SELECT T2.Col1,T2.Col2)更简洁。

–马丁·史密斯
2012年5月27日在9:44

该语句不应该在where子句中包含这两个吗? (other_table.col1为null且table.col1不为null)或(other_table.col2为null且table.col2不为null)

– Barka
13年5月15日在4:03



取决于是否要用源中的空值替换目标中的空值。通常,我不会。但是,如果这样做的话,最好使用Martin对where子句的构造。

–抢劫犯
13年5月16日在16:35

#5 楼

一种方法

UPDATE t 
SET t.col1 = o.col1, 
    t.col2 = o.col2
FROM 
    other_table o 
  JOIN 
    t ON t.id = o.id
WHERE 
    o.sql = 'cool'


#6 楼

尚未提及的另一种可能性是将SELECT语句本身插入CTE中,然后更新CTE。 SELECT语句首先要对结果进行完整性检查,但如果源列和目标表中的列名称相同,它确实需要您对列进行别名别名。

它也具有与以下列相同的限制其他四个答案中显示了专有的UPDATE ... FROM语法。如果源表位于一对多联接的多个端,则不确定在Update中将使用哪个可能匹配的联接记录(如果尝试执行以下操作,则MERGE会引发错误,从而避免了该问题:更新同一行不止一次)。

评论


CTE这个名字有什么意思吗?

–猛禽
2012年10月8日,12:48

@ShivanRaptor-它是Common Table Expression的首字母缩写。在这种情况下只是任意别名。

–马丁·史密斯
2012年10月8日13:05

这也适用于多个CTE:;带有SomeCompexCTE AS(...),CTEAsAbove AS(SELECT T1.Col1,... FROM T1 JOIN SomeComplexCTE ...)UPDATE CTEAsAbove SET Col1 = _Col1,...

–VeeTheSecond
13年8月29日在20:09



#7 楼

为了进行记录(以及其他类似的搜索记录),您可以像这样在MySQL中进行操作:

UPDATE first_table, second_table
SET first_table.color = second_table.color
WHERE first_table.id = second_table.foreign_id


#8 楼

使用别名:

UPDATE t
   SET t.col1 = o.col1
  FROM table1 AS t
         INNER JOIN 
       table2 AS o 
         ON t.id = o.id


#9 楼

简单的方法是:

UPDATE
    table_to_update,
    table_info
SET
    table_to_update.col1 = table_info.col1,
    table_to_update.col2 = table_info.col2

WHERE
    table_to_update.ID = table_info.ID


评论


这不是SQl Server语法,因此在SQL Server中不起作用

–HLGEM
13年4月24日在18:32

#10 楼

这可能是执行更新的利基原因(例如,主要在过程中使用),或者可能对其他人很明显,但是还应该指出,您可以在不使用join的情况下执行update-select语句(以防您要更新的表之间没有公共字段。

update
    Table
set
    Table.example = a.value
from
    TableExample a
where
    Table.field = *key value* -- finds the row in Table 
    AND a.field = *key value* -- finds the row in TableExample a


#11 楼

这是另一种有用的语法:

UPDATE suppliers
SET supplier_name = (SELECT customers.name
                     FROM customers
                     WHERE customers.customer_id = suppliers.supplier_id)
WHERE EXISTS (SELECT customers.name
              FROM customers
              WHERE customers.customer_id = suppliers.supplier_id);


它使用“ WHERE EXIST”检查它是否为null。

#12 楼

我仅添加它,以便您可以看到一种快速的编写方法,以便可以在执行更新之前检查将要更新的内容。

UPDATE Table 
SET  Table.col1 = other_table.col1,
     Table.col2 = other_table.col2 
--select Table.col1, other_table.col,Table.col2,other_table.col2, *   
FROM     Table 
INNER JOIN     other_table 
    ON     Table.id = other_table.id 


#13 楼

如果使用MySQL而不是SQL Server,则语法为:

 UPDATE Table1
INNER JOIN Table2
ON Table1.id = Table2.id
SET Table1.col1 = Table2.col1,
    Table1.col2 = Table2.col2
 


评论


如果我们要更新Table2.col1怎么办?我们将如何做到这一点。表2是根据查询条件提取的。

– Saad Abbasi
11月26日21:03

#14 楼

在SQL数据库中使用INNER JOIN从SELECT进行更新

由于这篇文章的回复太多,所以投票最多,我想我也会在这里提供我的建议。尽管这个问题非常有趣,但是我在很多论坛站点上都看到过,并使用带有截图的INNER JOIN提出了解决方案。

首先,我创建了一个名为schoolold的表,并插入了一些关于它们的列名并执行。

然后我执行SELECT命令来查看插入的记录。



然后我创建了一个名为的新表schoolnew,并对其执行类似的上述操作。



然后,要查看其中的插入记录,我执行SELECT命令。



现在,我想在第三和第四行中进行一些更改,以完成此操作,我使用INNER JOIN执行UPDATE命令。



要查看更改,请执行SELECT命令。



您可以看到如何通过使用INNER JOIN与tableschoolnew轻松地将table schoolold的第三和第四条记录替换为tableschoolnew UPDATE语句。

#15 楼

如果您想将表与自身连接(这种情况不会经常发生):

update t1                    -- just reference table alias here
set t1.somevalue = t2.somevalue
from table1 t1               -- these rows will be the targets
inner join table1 t2         -- these rows will be used as source
on ..................        -- the join clause is whatever suits you


评论


+1,但您应该使用相关的别名,例如targett1和sourcet1而不是(或)注释。

–马克·赫德
2014年6月30日在2:05

#16 楼

通过CTE更新比这里的其他答案更具可读性:

;WITH cte
     AS (SELECT col1,col2,id
         FROM   other_table
         WHERE  sql = 'cool')
UPDATE A
SET    A.col1 = B.col1,
       A.col2 = B.col2
FROM   table A
       INNER JOIN cte B
               ON A.id = B.id


#17 楼

下面的示例使用派生表,即FROM子句之后的SELECT语句,以返回旧值和新值以进行进一步更新:

UPDATE x
SET    x.col1 = x.newCol1,
       x.col2 = x.newCol2
FROM   (SELECT t.col1,
               t2.col1 AS newCol1,
               t.col2,
               t2.col2 AS newCol2
        FROM   [table] t
               JOIN other_table t2
                 ON t.ID = t2.ID) x


#18 楼

如果使用的是SQL Server,则可以在不指定联接的情况下从另一个表更新一个表,而只需从where子句链接两个表即可。这使SQL查询更加简单:

UPDATE Table1
SET Table1.col1 = Table2.col1,
    Table1.col2 = Table2.col2
FROM
    Table2
WHERE
    Table1.id = Table2.id


#19 楼

在这里合并所有不同的方法。


选择更新
使用通用表表达式进行更新
合并

示例表结构在下面和下面将从Product_BAK更新到产品表。

产品

CREATE TABLE [dbo].[Product](
    [Id] [int] IDENTITY(1, 1) NOT NULL,
    [Name] [nvarchar](100) NOT NULL,
    [Description] [nvarchar](100) NULL
) ON [PRIMARY]


Product_BAK

    CREATE TABLE [dbo].[Product_BAK](
        [Id] [int] IDENTITY(1, 1) NOT NULL,
        [Name] [nvarchar](100) NOT NULL,
        [Description] [nvarchar](100) NULL
    ) ON [PRIMARY]


1。选择更新

    update P1
    set Name = P2.Name
    from Product P1
    inner join Product_Bak P2 on p1.id = P2.id
    where p1.id = 2


2。使用通用表表达式进行更新

    ; With CTE as
    (
        select id, name from Product_Bak where id = 2
    )
    update P
    set Name = P2.name
    from  product P  inner join CTE P2 on P.id = P2.id
    where P2.id = 2


3。合并

    Merge into product P1
    using Product_Bak P2 on P1.id = P2.id

    when matched then
    update set p1.[description] = p2.[description], p1.name = P2.Name;


在此Merge语句中,如果未在目标中找到匹配记录但在源中存在匹配记录,则可以进行插入操作,请查找语法:

    Merge into product P1
    using Product_Bak P2 on P1.id = P2.id;

    when matched then
    update set p1.[description] = p2.[description], p1.name = P2.Name;

    WHEN NOT MATCHED THEN
    insert (name, description)
    values(p2.name, P2.description);


#20 楼

另一种方法是使用派生表:

UPDATE t
SET t.col1 = a.col1
    ,t.col2 = a.col2
FROM (
SELECT id, col1, col2 FROM @tbl2) a
INNER JOIN @tbl1 t ON t.id = a.id



样本数据

DECLARE @tbl1 TABLE (id INT, col1 VARCHAR(10), col2 VARCHAR(10))
DECLARE @tbl2 TABLE (id INT, col1 VARCHAR(10), col2 VARCHAR(10))

INSERT @tbl1 SELECT 1, 'a', 'b' UNION SELECT 2, 'b', 'c'

INSERT @tbl2 SELECT 1, '1', '2' UNION SELECT 2, '3', '4'

UPDATE t
SET t.col1 = a.col1
    ,t.col2 = a.col2
FROM (
SELECT id, col1, col2 FROM @tbl2) a
INNER JOIN @tbl1 t ON t.id = a.id

SELECT * FROM @tbl1
SELECT * FROM @tbl2


#21 楼

UPDATE TQ
SET TQ.IsProcessed = 1, TQ.TextName = 'bla bla bla'
FROM TableQueue TQ
INNER JOIN TableComment TC ON TC.ID = TQ.TCID
WHERE TQ.IsProcessed = 0


要确保您要更新的内容,请先选择

SELECT TQ.IsProcessed, 1 AS NewValue1, TQ.TextName, 'bla bla bla' AS NewValue2
FROM TableQueue TQ
INNER JOIN TableComment TC ON TC.ID = TQ.TCID
WHERE TQ.IsProcessed = 0


#22 楼

甚至有一个更短的方法,这可能会让您感到惊讶:

样本数据集:

CREATE TABLE #SOURCE ([ID] INT, [Desc] VARCHAR(10));
CREATE TABLE #DEST   ([ID] INT, [Desc] VARCHAR(10));

INSERT INTO #SOURCE VALUES(1,'Desc_1'), (2, 'Desc_2'), (3, 'Desc_3');
INSERT INTO #DEST   VALUES(1,'Desc_4'), (2, 'Desc_5'), (3, 'Desc_6');


代码:

UPDATE #DEST
SET #DEST.[Desc] = #SOURCE.[Desc]
FROM #SOURCE
WHERE #DEST.[ID] = #SOURCE.[ID];


评论


是-故意没有JOIN,否-不能应用于表变量。

– Bartosz X
17年1月26日在13:30

我认为,如果您在#SOURCE上使用[_id]而不是与#DESTINATION的[ID]相同,则它们可能会让您加入JOIN。 “在#DESTINATION.ID =#SOURCE._id上。或者甚至使用@tbl这样的表变量,在PermTable.ID=@memorytbl._id上。您尝试过吗?我正在用电话回复此信息,没有计算机可以尝试。

–珍娜·叶
17年2月3日在15:53



这与从SELECT更新有什么关系?

–马丁·史密斯
17年2月5日在18:10

这是相同的想法,但是是另一种方法-您根本不必在更新语句中使用“选择”来实现JOIN和WHERE-这是SELECT类型的查询,甚至无需编写SELECT

– Bartosz X
17年2月5日在18:19

#23 楼

用途:

drop table uno
drop table dos

create table uno
(
    uid int,
    col1 char(1),
    col2 char(2)
)
create table dos
(
    did int,
    col1 char(1),
    col2 char(2),
    [sql] char(4)
)
insert into uno(uid) values (1)
insert into uno(uid) values (2)
insert into dos values (1,'a','b',null)
insert into dos values (2,'c','d','cool')

select * from uno 
select * from dos


EITHER:

update uno set col1 = (select col1 from dos where uid = did and [sql]='cool'), 
col2 = (select col2 from dos where uid = did and [sql]='cool')


OR:

update uno set col1=d.col1,col2=d.col2 from uno 
inner join dos d on uid=did where [sql]='cool'

select * from uno 
select * from dos


如果两个表中的ID列名称相同,则只需将表名称放在要更新的表之前,并对所选表使用别名,即:

update uno set col1 = (select col1 from dos d where uno.[id] = d.[id] and [sql]='cool'),
col2  = (select col2 from dos d where uno.[id] = d.[id] and [sql]='cool')


#24 楼

在接受的答案中,在:

SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2


之后,我要添加:

OUTPUT deleted.*, inserted.*


我通常做什么正在将所有内容放入回滚事务中并使用"OUTPUT":通过这种方式,我看到了即将发生的一切。当我对看到的内容感到满意时,我将ROLLBACK更改为COMMIT

我通常需要记录所做的事情,因此在运行回滚查询时我使用"results to Text"选项并保存脚本和OUTPUT的结果。 (如果我更改了太多行,这当然是不切实际的)

#25 楼

UPDATE table AS a
INNER JOIN table2 AS b
ON a.col1 = b.col1
INNER JOIN ... AS ...
ON ... = ...
SET ...
WHERE ...


#26 楼

以下解决方案适用于MySQL数据库:

UPDATE table1 a , table2 b 
SET a.columname = 'some value' 
WHERE b.columnname IS NULL ;


#27 楼

从select语句更新的另一种方法:

UPDATE A
SET A.col = A.col,B.col1 = B.col1
FROM  first_Table AS A
INNER JOIN second_Table AS B  ON A.id = B.id WHERE A.col2 = 'cool'


评论


这个答案出现在低质量的审阅队列中,大概是因为您没有提供任何代码说明。如果此代码回答了问题,请考虑在回答中添加一些解释该代码的文本。这样,您更有可能获得更多的赞誉,并帮助提问者学习新的知识。

–lmo
2016年9月8日在22:09

#28 楼

选项1:使用内部联接:

UPDATE
    A
SET
    A.col1 = B.col1,
    A.col2 = B.col2
FROM
    Some_Table AS A
    INNER JOIN Other_Table AS B
        ON A.id = B.id
WHERE
    A.col3 = 'cool'


选项2:与公司相关的子查询

UPDATE table 
SET Col1 = B.Col1, 
    Col2 = B.Col2 
FROM (
    SELECT ID, Col1, Col2 
    FROM other_table) B
WHERE 
    B.ID = table.ID


评论


它对您有用吗?我使用完全相同的查询,但在使用内部联接时出现错误,别名无法解析。但是,相关的子查询运行良好。

– Pratyush Raizada
19/11/26在15:12



我没有确切的错误日志,但分配前已引用别名A,这导致了错误。

– Pratyush Raizada
1月7日8:16

我使用了相关子查询

– pat capozzi
3月19日18:14

#29 楼

UPDATE table1
SET column1 = (SELECT expression1
               FROM table2
               WHERE conditions)
[WHERE conditions];


用SQL Server中的另一个表中的数据更新一个表时UPDATE语句的语法

#30 楼

与其他人一样,需要指出的是,MySQL或MariaDB使用不同的语法。它还支持非常方便的USING语法。 INNER JOIN也是JOIN的同义词。因此,原始问题中的查询最好在MySQL中实现:
UPDATE
    Some_Table AS Table_A

JOIN
    Other_Table AS Table_B USING(id)

SET
    Table_A.col1 = Table_B.col1,
    Table_A.col2 = Table_B.col2

WHERE
    Table_A.col3 = 'cool'

在其他答案中,我没有看到针对原始询问的解决方案,因此我只有2美分。 >(已在PHP 7.4.0 MariaDB 10.4.10上测试)