提问



SQL Server 中,可以使用SELECT语句将insert放入表中:


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'

其它参考1


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


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;

其它参考2


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

其它参考3


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


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

其它参考4


单程


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'

其它参考5


另一种未提及的可能性是将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语句来检查结果的完整性,但如果在源表和目标表中它们的名称相同,它确实需要您按上述方式对列进行别名。


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

其它参考6


对于记录(以及其他像我一样的搜索),你可以在MySQL中这样做:


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

其它参考7


使用别名:


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

其它参考8


简单的方法是:


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

其它参考9


这可能是执行更新的一个利基理由(例如,主要用于过程),或者对其他人来说可能是显而易见的,但是还应该声明您可以在不使用连接的情况下执行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

其它参考10


这是另一个有用的语法:


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。

其它参考11


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


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 

其它参考12


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


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

其它参考13


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


由于这篇文章的回复太多,而且投票率最高,我想我也会在这里提出我的建议。虽然这个问题非常有趣,但我在许多论坛网站上都看到过并使用 INNER JOIN 制作了截图解决方案。


首先,我创建了一个名为 schoolold 的表,并插入了几个与其列名相关的记录并执行它。


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


[59]


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


[60]


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


[61]


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


[62]


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


[63]


通过使用INNER JOIN和UPDATE语句,您可以看到表 schoolold 的第三和第四条记录如何轻松替换为表 schoolnew

其它参考14


如果你想加入自己的桌子(这种情况不会经常发生):


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

其它参考15


以下示例使用派生表(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

其它参考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


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


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

其它参考18


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


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

其它参考19


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

其它参考20


使用:


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

其它参考21


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


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

其它参考22


甚至有一个更短的方法,对你们许多人来说可能会令人惊讶:


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

其它参考23


在接受的答案中,在:


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


我想补充一下:


OUTPUT deleted.*, inserted.*


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


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

其它参考24


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

其它参考25


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

其它参考26


整合所有不同的方法......



  1. 选择更新

  2. 使用公用表格表达式进行更新

  3. 合并



样本表结构:


产品



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