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'
#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上测试)
评论
如果要编辑表之间的链接(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