如何从SQL Server中的SELECT进行更新?

在SQL Server中,可以使用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 
 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' 

在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; 
 UPDATE table SET Col1 = i.Col1, Col2 = i.Col2 FROM ( SELECT ID, Col1, Col2 FROM other_table) i WHERE i.ID = table.ID 

我会修改罗宾的优秀答案如下:

 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子句,甚至会影响不需要影响的行,这可能(可能)导致索引重新计算或触发器实际上不应该被触发。

单程

 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' 

另一个没有提到的可能性是把SELECT语句本身放到CTE中,然后更新CTE。

 ;WITH CTE AS (SELECT T1.Col1, T2.Col1 AS _Col1, T1.Col2, T2.Col2 AS _Col2 FROM T1 JOIN T2 ON T1.id = T2.id /*Where clause added to exclude rows that are the same in both tables Handles NULL values correctly*/ WHERE EXISTS(SELECT T1.Col1, T1.Col2 EXCEPT SELECT T2.Col1, T2.Col2)) UPDATE CTE SET Col1 = _Col1, Col2 = _Col2 

这有一个好处,就是很容易首先运行SELECT语句来检查结果的完整性,但是如果它们在源表和目标表中被命名为相同的,那么它确实需要为上面的列创build别名。

这也与其他四个答案中显示的专有UPDATE ... FROM语法具有相同的限制。 如果源表在一对多连接的许多方面,那么在Update中将使用哪些可能的匹配连接logging是不确定的( MERGE通过在尝试更新同一行不止一次)。

对于logging(和其他search像我一样),你可以在MySQL中这样做:

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

使用别名:

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

简单的方法是:

 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 

这可能是执行更新(例如,主要用于过程)的一个利基原因,或者对其他人可能是显而易见的,但是也应该说明,您可以执行更新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 

这是另一个有用的语法:

 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”来检查它是否为空。

我只是添加这个,所以你可以看到一个快速的方式来写它,以便您可以检查更新之前将会更新。

 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 

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

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

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

由于这篇文章的回复太多,而这些回覆最多,所以我想我也会在这里提出我的build议。 虽然这个问题非常有趣,但是我在很多论坛上都看到过,使用INNER JOIN和截图做了一个解决scheme。

起初,我创build了一个以schoolold命名的表,并插入了一些关于它们的列名的logging并执行它。

然后我执行SELECT命令查看插入的logging。

在这里输入图像描述

然后,我创build了一个新的名为新学校的表,同样执行上面的行动。

在这里输入图像描述

然后,要查看插入的logging,我执行SELECT命令。

在这里输入图像描述

现在,在这里我想在第三和第四行进行一些更改,为了完成这个动作,我使用INNER JOIN执行UPDATE命令。

在这里输入图像描述

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

在这里输入图像描述

你可以通过使用INNER JOIN和UPDATE语句来看到table schoolold的第三和第四条logging是如何轻松replacetablenew的。

如果你想和自己一起参加表(这不会经常发生):

 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 

以下示例使用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 

通过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 

如果您使用的是SQL Server,则可以更新另一个表而不指定连接,只需将where子句中的两个链接即可。 这使得一个更简单的SQL查询:

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

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

 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 
 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

 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 
 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 

无论是:

 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') 

要么:

 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') 

我终于得到这个简单的解决scheme

 UPDATE table1 a , table2 b SET a.columname = 'some value' WHERE b.columnname IS NULL ; 
 The other way to update from select statement : 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' 

甚至有更短的方法,可能会让你们中的许多人感到惊讶:

 -- Sample data: --------------------------------------------------------------------------- CREATE TABLE #SOURCE ([ID] INT, [Desc] VARCHAR(10)); CREATE TABLE #DESTINATION ([ID] INT, [Desc] VARCHAR(10)) INSERT INTO #SOURCE VALUES(1,'Desc_1'), (2, 'Desc_2'), (3, 'Desc_3'); INSERT INTO #DESTINATION VALUES(1,'Desc_4'), (2, 'Desc_5'), (3, 'Desc_6'); --------------------------------------------------------------------------- UPDATE #DESTINATION SET #DESTINATION.[Desc] = #SOURCE.[Desc] FROM #SOURCE WHERE #DESTINATION.[ID] = #SOURCE.[ID] AND #Source.[Desc] = 'Desc_2' 
 UPDATE table AS a INNER JOIN table2 AS b ON a.col1 = b.col1 INNER JOIN ... AS ... ON ... = ... SET ... WHERE ... 

在接受的答案中,在:

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

我会补充一点:

 OUTPUT deleted.*, inserted.* 

我通常所做的就是把所有事情都放在一个回滚事务中,并使用“OUTPUT”:这样我就能看到即将发生的一切。 当我对我所看到的满意时,我将ROLLBACK更改为COMMIT。

我通常需要logging我做了什么,所以我运行回滚查询时使用“结果到文本”选项,同时保存脚本和OUTPUT的结果。 (当然,如果我改变了太多的行,这是不实际的)