如何从SQL服务器中的SELECT更新?

SQL服务器中,可以使用INSERT.. SELECT语句将行插入表中:

INSERT INTO Table (col1, col2, col3)SELECT col1, col2, col3FROM other_tableWHERE sql = 'cool'

是否也可以用SELECT更新表?我有一个包含值的临时表,并想使用这些值更新另一个表。也许像这样:

UPDATE Table SET col1, col2SELECT col1, col2FROM other_tableWHERE sql = 'cool'WHERE Table.id = other_table.id
5033045 次浏览
UPDATETable_ASETTable_A.col1 = Table_B.col1,Table_A.col2 = Table_B.col2FROMSome_Table AS Table_AINNER JOIN Other_Table AS Table_BON Table_A.id = Table_B.idWHERETable_A.col3 = 'cool'

一种方式

UPDATE tSET t.col1 = o.col1,t.col2 = o.col2FROMother_table oJOINt ON t.id = o.idWHEREo.sql = 'cool'

我将罗宾的精彩回答修改为以下内容:

UPDATE TableSET Table.col1 = other_table.col1,Table.col2 = other_table.col2FROMTableINNER JOIN other_table ON Table.id = other_table.idWHERETable.col1 != other_table.col1OR Table.col2 != other_table.col2OR (other_table.col1 IS NOT NULLAND Table.col1 IS NULL)OR (other_table.col2 IS NOT NULLAND Table.col2 IS NULL)

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

我添加这个只是为了让您可以看到一个快速编写它的方法,以便您可以在更新之前检查将更新的内容。

UPDATE TableSET  Table.col1 = other_table.col1,Table.col2 = other_table.col2--select Table.col1, other_table.col,Table.col2,other_table.col2, *FROM     TableINNER JOIN     other_tableON     Table.id = other_table.id

在SQLServer 2008(或更高版本)中,使用#0

MERGE INTO YourTable TUSING other_table SON T.id = S.idAND S.tsql = 'cool'WHEN MATCHED THENUPDATESET col1 = S.col1,col2 = S.col2;

或者:

MERGE INTO YourTable TUSING (SELECT id, col1, col2FROM other_tableWHERE tsql = 'cool') SON T.id = S.idWHEN MATCHED THENUPDATESET col1 = S.col1,col2 = S.col2;

另一种尚未提及的可能性是将SELECT语句本身扔进CTE,然后更新CTE。

WITH CTEAS (SELECT T1.Col1,T2.Col1 AS _Col1,T1.Col2,T2.Col2 AS _Col2FROM   T1JOIN T2ON T1.id = T2.id/*Where clause added to exclude rows that are the same in both tablesHandles NULL values correctly*/WHERE EXISTS(SELECT T1.Col1,T1.Col2EXCEPTSELECT T2.Col1,T2.Col2))UPDATE CTESET    Col1 = _Col1,Col2 = _Col2;

这样做的好处是,首先很容易自己运行SELECT语句来检查结果是否正确,但如果列在源表和目标表中的名称相同,则需要您像上面一样为列别名。

这也与其他四个答案中显示的专有UPDATE ... FROM语法具有相同的限制。如果源表位于一对多连接的多侧,那么Update中将使用哪些可能匹配的连接记录是不确定的(如果尝试多次更新同一行,MERGE通过引发错误来避免这个问题)。

UPDATE YourTableSET Col1 = OtherTable.Col1,Col2 = OtherTable.Col2FROM (SELECT ID, Col1, Col2FROM other_table) AS OtherTableWHEREOtherTable.ID = YourTable.ID

使用别名:

UPDATE tSET t.col1 = o.col1FROM table1 AS tINNER JOINtable2 AS oON t.id = o.id

这可能是执行更新的一个小原因(例如,主要用于过程),或者对其他人来说可能是显而易见的,但还应该指出,您可以在不使用连接的情况下执行update-选择语句(如果您正在更新的表之间没有公共字段)。

updateTablesetTable.example = a.valuefromTableExample awhereTable.field = *key value* -- finds the row in TableAND a.field = *key value* -- finds the row in TableExample a

为了记录(和其他像我一样搜索的人),你可以在MySQL中这样做:

UPDATE first_table, second_tableSET first_table.color = second_table.colorWHERE first_table.id = second_table.foreign_id

简单的方法是:

UPDATEtable_to_update,table_infoSETtable_to_update.col1 = table_info.col1,table_to_update.col2 = table_info.col2
WHEREtable_to_update.ID = table_info.ID

这是另一个有用的语法:

UPDATE suppliersSET supplier_name = (SELECT customers.nameFROM customersWHERE customers.customer_id = suppliers.supplier_id)WHERE EXISTS (SELECT customers.nameFROM customersWHERE customers.customer_id = suppliers.supplier_id);

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

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

UPDATE xSET    x.col1 = x.newCol1,x.col2 = x.newCol2FROM   (SELECT t.col1,t2.col1 AS newCol1,t.col2,t2.col2 AS newCol2FROM   [table] tJOIN other_table t2ON t.ID = t2.ID) x

如果使用mysql而不是SQLServer,则语法为:

UPDATE Table1INNER JOIN Table2ON Table1.id = Table2.idSET Table1.col1 = Table2.col1,Table1.col2 = Table2.col2

用途:

drop table unodrop 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 unoselect * 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 unoinner join dos d on uid=did where [sql]='cool'
select * from unoselect * 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')

如果你想加入表本身(这不会经常发生):

update t1                    -- just reference table alias hereset t1.somevalue = t2.somevaluefrom table1 t1               -- these rows will be the targetsinner join table1 t2         -- these rows will be used as sourceon ..................        -- the join clause is whatever suits you

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

UPDATE table1 a , table2 bSET a.columname = 'some value'WHERE b.columnname IS NULL ;
UPDATE table AS aINNER JOIN table2 AS bON a.col1 = b.col1INNER JOIN ... AS ...ON ... = ...SET ...WHERE ...

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

由于这篇文章的回复太多了,投票最多,我想我也会在这里提供我的建议。虽然这个问题很有趣,但我在许多论坛网站上看到并用截图内连接做了一个解决方案。

首先,我创建了一个名为学童的表,并根据它们的列名插入了一些记录并执行它。

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

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

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

现在,在这里我想在第三行和第四行进行一些更改,为了完成这个动作,我用内连接执行更新命令。

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

您可以看到如何使用INNER JOIN with UPDATE语句轻松地将表学童的第三条和第四条记录替换为表新学校

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

;WITH cteAS (SELECT col1,col2,idFROM   other_tableWHERE  sql = 'cool')UPDATE ASET    A.col1 = B.col1,A.col2 = B.col2FROM   table AINNER JOIN cte BON A.id = B.id

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

UPDATE tSET t.col1 = a.col1,t.col2 = a.col2FROM (SELECT id, col1, col2 FROM @tbl2) aINNER 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 tSET t.col1 = a.col1,t.col2 = a.col2FROM (SELECT id, col1, col2 FROM @tbl2) aINNER JOIN @tbl1 t ON t.id = a.id
SELECT * FROM @tbl1SELECT * FROM @tbl2

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

UPDATE ASET A.col = A.col,B.col1 = B.col1FROM  first_Table AS AINNER JOIN second_Table AS B  ON A.id = B.id WHERE A.col2 = 'cool'
UPDATE TQSET TQ.IsProcessed = 1, TQ.TextName = 'bla bla bla'FROM TableQueue TQINNER JOIN TableComment TC ON TC.ID = TQ.TCIDWHERE TQ.IsProcessed = 0

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

SELECT TQ.IsProcessed, 1 AS NewValue1, TQ.TextName, 'bla bla bla' AS NewValue2FROM TableQueue TQINNER JOIN TableComment TC ON TC.ID = TQ.TCIDWHERE TQ.IsProcessed = 0

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

示例数据集:

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 #DESTSET #DEST.[Desc] = #SOURCE.[Desc]FROM #SOURCEWHERE #DEST.[ID] = #SOURCE.[ID];

如果您使用SQLServer,您可以从另一个表更新一个表,而无需指定连接,只需从where子句链接两个表。这使得SQL查询简单得多:

UPDATE Table1SET Table1.col1 = Table2.col1,Table1.col2 = Table2.col2FROMTable2WHERETable1.id = Table2.id

在接受的答案中,在:

SETTable_A.col1 = Table_B.col1,Table_A.col2 = Table_B.col2

我要补充:

OUTPUT deleted.*, inserted.*

我通常做的是将所有内容放入滚动支持的事务中并使用"OUTPUT":这样我就可以看到即将发生的一切。当我对我所看到的感到满意时,我将ROLLBACK更改为COMMIT

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

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

  1. 选择更新
  2. 使用公共表表达式进行更新
  3. 合并

示例表结构如下,将从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 P1set Name = P2.Namefrom Product P1inner join Product_Bak P2 on p1.id = P2.idwhere p1.id = 2

2.使用通用表表达式更新

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

3.合并

    Merge into product P1using Product_Bak P2 on P1.id = P2.id
when matched thenupdate set p1.[description] = p2.[description], p1.name = P2.Name;

在这个合并语句中,如果在目标中没有找到匹配的记录,但存在于源中,请查找语法,我们可以执行插入:

    Merge into product P1using Product_Bak P2 on P1.id = P2.id;
when matched thenupdate set p1.[description] = p2.[description], p1.name = P2.Name;
WHEN NOT MATCHED THENinsert (name, description)values(p2.name, P2.description);

您可以在SQLServer中使用此更新:

UPDATET1SETT1.col1 = T2.col1,T1.col2 = T2.col2FROMTable1 AS T1INNER JOIN Table2 AS T2ON T1.id = T2.idWHERET1.col3 = 'cool'
declare @tblStudent table (id int,name varchar(300))declare @tblMarks table (std_id int,std_name varchar(300),subject varchar(50),marks int)
insert into @tblStudent Values (1,'Abdul')insert into @tblStudent Values(2,'Rahim')
insert into @tblMarks Values(1,'','Math',50)insert into @tblMarks Values(1,'','History',40)insert into @tblMarks Values(2,'','Math',30)insert into @tblMarks Values(2,'','history',80)

select * from @tblMarks
update mset m.std_name=s.namefrom @tblMarks as mleft join @tblStudent as s on s.id=m.std_id
select * from @tblMarks

选项1:使用内连接:

UPDATEASETA.col1 = B.col1,A.col2 = B.col2FROMSome_Table AS AINNER JOIN Other_Table AS BON A.id = B.idWHEREA.col3 = 'cool'

选项2:相关子查询

UPDATE tableSET Col1 = B.Col1,Col2 = B.Col2FROM (SELECT ID, Col1, Col2FROM other_table) BWHEREB.ID = table.ID

相同的解决方案可以用稍微不同的方式编写,因为我只想设置一次列。我已经写了两个表。它在mysql中工作。

UPDATE Table t,(SELECT col1, col2 FROM other_table WHERE sql = 'cool' ) oSET t.col1 = o.col1, t.col2=o.col2WHERE t.id = o.id

像这样;但你必须确保更新表和表后从有是一样的。

UPDATE Table SET col1, col2FROM tableinner join other_table Table.id = other_table.idWHERE sql = 'cool'
UPDATE table1SET column1 = (SELECT expression1FROM table2WHERE conditions)[WHERE conditions];

使用服务器中另一个表中的数据更新一个表时UPDATE语句SQL语法。

我以前使用过INSERT SELECT。对于那些想使用新东西的人来说,这里有一个类似的解决方案,但它要短得多:

UPDATE table1                                          // Table that's going to be updated.LEFT JOIN                                              // Type of join.table2 AS tb2                                      // Second table and rename for easy.ONtb2.filedToMatchTables = table1.fieldToMatchTables // Fields to connect both tables.SETfieldFromTable1 = tb2.fieldFromTable2;             // Field to be updated on table1.
field1FromTable1 = tb2.field1FromTable2,           // This is in the case you need tofield1FromTable1 = tb2.field1FromTable2,           // update more than one field.field1FromTable1 = tb2.field1FromTable2;           // Remember to put ; at the end.

重要的是要指出,和其他人一样,mysqlMariaDB使用不同的语法。它还支持非常方便的USING语法(与T/SQL相反)。此外,INNER JOIN是JOIN的同义词。因此,最初问题中的查询最好在MySQL中实现:

UPDATESome_Table AS Table_A
JOINOther_Table AS Table_B USING(id)
SETTable_A.col1 = Table_B.col1,Table_A.col2 = Table_B.col2
WHERETable_A.col3 = 'cool'

我在其他答案中没有看到所问问题的答案,因此我的两分钱。(在PHP 7.4.0 MariaDB 10.4.10上测试)

最佳实践在公司使用的SQLServer中更新行和保险箱

 WITH t AS(SELECT UserID, EmailAddress, Password, Gender, DOB, Location,Active  FROM Facebook.Users)UPDATE t SET Active = 0

这是最安全的方式来更新记录,这就是你可以看到我们要更新的内容。来源:url

OracleSQL(使用别名):

UPDATE Table TSET T.col1 = (SELECT OT.col1 WHERE OT.id = T.id),T.col2 = (SELECT OT.col2 WHERE OT.id = T.id);