SQL根据ID匹配从一个表更新到另一个表


929

我有一个与account numbers和的数据库card numbers。我将这些文件匹配到文件,将update任何卡号匹配到该帐号,所以我只使用帐号。

我创建了一个将表链接到帐户/卡数据库的视图,以返回Table ID和相关的帐号,现在我需要更新ID与帐号匹配的那些记录。

这是Sales_Import表格,其中的account number字段需要更新:

LeadID  AccountNumber
147         5807811235
150         5807811326
185         7006100100007267039

这是RetrieveAccountNumber表格,我需要从这里更新:

LeadID  AccountNumber
147         7006100100007266957
150         7006100100007267039

我尝试了以下方法,但到目前为止没有运气:

UPDATE [Sales_Lead].[dbo].[Sales_Import] 
SET    [AccountNumber] = (SELECT RetrieveAccountNumber.AccountNumber 
                          FROM   RetrieveAccountNumber 
                          WHERE  [Sales_Lead].[dbo].[Sales_Import]. LeadID = 
                                                RetrieveAccountNumber.LeadID) 

它将卡号更新为帐号,但是帐号被替换为 NULL

Answers:


1368

我相信一个UPDATE FROMJOIN意愿帮助:

MS SQL

UPDATE
    Sales_Import
SET
    Sales_Import.AccountNumber = RAN.AccountNumber
FROM
    Sales_Import SI
INNER JOIN
    RetrieveAccountNumber RAN
ON 
    SI.LeadID = RAN.LeadID;

MySQL和MariaDB

UPDATE
    Sales_Import SI,
    RetrieveAccountNumber RAN
SET
    SI.AccountNumber = RAN.AccountNumber
WHERE
    SI.LeadID = RAN.LeadID;

18
您可能想在UPDATE子句中使用表别名,否则,如果您在任何时候自行加入表,都会导致问题。
汤姆H”

15
在set子句中,您应该更改SI.AccountNumber为,AccountNumber否则它将失败。
AaronLS

1
MS-Access对JOIN语句使用其他UPDATE。看一看:sql-und-xml.de/sql-tutorial/...
基督教阿默尔

92
这对于mssql似乎很好,但在mysql中似乎不起作用。不过,这似乎可以完成工作:UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;。稍微偏离主题,但可能会有所帮助
Edd 2012年

7
我认为不需要内部联接。下面作品Vonki溶液:UPDATE [Sales_Lead] [DBO] [Sales_Import] SET [账户号码] = RetrieveAccountNumber.AccountNumber FROM RetrieveAccountNumber WHERE [Sales_Lead] [DBO] [Sales_Import] .LeadID =
Gutti

289

将内容从一个表复制到另一个表的简单方法如下:

UPDATE table2 
SET table2.col1 = table1.col1, 
table2.col2 = table1.col2,
...
FROM table1, table2 
WHERE table1.memberid = table2.memberid

您还可以添加条件以复制特定数据。


2
这可行,但是您不需要FROM UPDATE table2中的table2 SET table2.col1 = table1.col1,table2.col2 = table1.col2,... FROM table1 WHERE table1.memberid = table2.memberid
Sirentec

2
这没有用,但是UPDATE table2,table1 SET table2.col1 = table1.col1,... WHERE table1.memberid = table2.memberid(mysql和phpmyadmin)
Tom Kuschel

156

对于SQL Server 2008 +,使用MERGE而不是专有UPDATE ... FROM语法具有吸引力。

除了作为标准SQL并因此具有更大的可移植性之外,如果在源端有多个连接的行(并因此在更新中使用多个可能的不同值),它也会引发错误,而不是最终结果不确定。

MERGE INTO Sales_Import
   USING RetrieveAccountNumber
      ON Sales_Import.LeadID = RetrieveAccountNumber.LeadID
WHEN MATCHED THEN
   UPDATE 
      SET AccountNumber = RetrieveAccountNumber.AccountNumber;

不幸的是,使用哪种选择可能不会完全归结为首选样式。MERGE在SQL Server中的实现已受到各种错误的困扰。亚伦·伯特兰德(Aaron Bertrand)在这里汇编了一份报道的清单。


11
前往MERGE
Jakub Januszkiewicz 2012年

2
我从不知道合并语法。它比“更新+加入”要干净得多。
Tony Ashworth

+1用于报告MERGE SQL Server的实现
AFract 2013年

1
使用MERGE的参数(包括上面链接的sqlblog.com的帖子中的参数)可能令人信服,但根据MSDN,要考虑的一件事可能是:当两个表包含以下内容的复杂混合物时,... MERGE语句最有效匹配特征...当仅基于另一个表的行更新一个表时,可以使用基本的INSERT,UPDATE和DELETE语句实现更高的性能和可伸缩性
Tony Pulokas 16-10-27

1
@ jkp1187这个问题被标记为SQL Server。因此RE:FWIW-大约为零。
马丁·史密斯

104

未来开发人员的通用答案。

SQL服务器

UPDATE 
     t1
SET 
     t1.column = t2.column
FROM 
     Table1 t1 
     INNER JOIN Table2 t2 
     ON t1.id = t2.id;

Oracle(和SQL Server)

UPDATE 
     t1
SET 
     t1.colmun = t2.column 
FROM 
     Table1 t1, 
     Table2 t2 
WHERE 
     t1.ID = t2.ID;

的MySQL

UPDATE 
     Table1 t1, 
     Table2 t2
SET 
     t1.column = t2.column 
WHERE
     t1.ID = t2.ID;

2
值得注意的是,至少对于SQL Server,在顶部update子句(update t1...而不是update Table1...)中使用别名而不是表名
gordon

2
Oracle版本不起作用。正在获取ORA-00933
ka3ak

35

对于PostgreSQL:

UPDATE Sales_Import SI
SET AccountNumber = RAN.AccountNumber
FROM RetrieveAccountNumber RAN
WHERE RAN.LeadID = SI.LeadID; 

34

似乎您正在使用MSSQL,然后,如果我没记错的话,它是这样完成的:

UPDATE [Sales_Lead].[dbo].[Sales_Import] SET [AccountNumber] = 
RetrieveAccountNumber.AccountNumber 
FROM RetrieveAccountNumber 
WHERE [Sales_Lead].[dbo].[Sales_Import].LeadID = RetrieveAccountNumber.LeadID

33

我对于在中没有匹配键的行foo.new设置为同样的问题。我在Oracle中做了这样的事情:nullfoobar

更新foo
设置foo.new =(选择bar.new
                  从酒吧 
                  其中foo.key = bar.key)
存在的地方(选择1
              从酒吧
              其中foo.key = bar.key)

4
为什么需要“在哪里存在”
GeorgSchölly10年

6
因为foo中的每一行在bar中没有匹配项,最终都为null,因为select语句产生了null。希望这比我第一次尝试解释时更清楚。
Kjell Andreassen


@KjellAndreassen您已经解决了我的问题。感谢您的代码。
Bhavin Thummar,

27

对于运行良好的MySql:

UPDATE
    Sales_Import SI,RetrieveAccountNumber RAN
SET
    SI.AccountNumber = RAN.AccountNumber
WHERE
    SI.LeadID = RAN.LeadID

26

这是在SQL Server中对我有用的东西:

UPDATE [AspNetUsers] SET

[AspNetUsers].[OrganizationId] = [UserProfile].[OrganizationId],
[AspNetUsers].[Name] = [UserProfile].[Name]

FROM [AspNetUsers], [UserProfile]
WHERE [AspNetUsers].[Id] = [UserProfile].[Id];

18

感谢您的答复。我找到了解决办法。

UPDATE Sales_Import 
SET    AccountNumber = (SELECT RetrieveAccountNumber.AccountNumber 
                          FROM   RetrieveAccountNumber 
                          WHERE  Sales_Import.leadid =RetrieveAccountNumber.LeadID) 
WHERE Sales_Import.leadid = (SELECT  RetrieveAccountNumber.LeadID 
                             FROM   RetrieveAccountNumber 
                             WHERE  Sales_Import.leadid = RetrieveAccountNumber.LeadID)  

17
无论此处的代码是否有效,您都应该查看发布的其他两个解决方案。它们更加清晰,不易出错,而且几乎可以肯定更快。
汤姆·H

3
只是关于此解决方案的说明,因此UPDATE ... FROM是专有的,如果由于使用SQL 2005或更早版本而无法使用MERGE语句,则这是一种与ANSI兼容的方法,用于对MSSQL中的表源执行更新。资料来源:sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/…–

1
唯一适用于我的解决方案,因为它具有标准的SQL更新语句(UPDATE SET WHERE),非常感谢
Basheer AL-MOMANI

13

如果表位于不同的数据库中。(MSSQL)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

FROM database1..Ciudad c1
 inner join 
  database2..Ciudad c2 on c2.CiudadID=c1.CiudadID

10

使用以下查询块根据ID将Table1更新为Table2:

UPDATE Sales_Import, RetrieveAccountNumber 
SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber 
where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;

这是解决此问题的最简单方法


8

微软SQL

UPDATE  c4 SET Price=cp.Price*p.FactorRate FROM TableNamea_A c4
inner join TableNamea_B p on c4.Calcid=p.calcid 
inner join TableNamea_A cp on c4.Calcid=cp.calcid 
WHERE c4..Name='MyName';

甲骨文11g

        MERGE INTO  TableNamea_A u 
        using
        (
                SELECT c4.TableName_A_ID,(cp.Price*p.FactorRate) as CalcTot 
                FROM TableNamea_A c4
                inner join TableNamea_B p on c4.Calcid=p.calcid 
                inner join TableNamea_A cp on c4.Calcid=cp.calcid 
                WHERE p.Name='MyName' 
        )  rt
        on (u.TableNamea_A_ID=rt.TableNamea_B_ID)
        WHEN MATCHED THEN
        Update set Price=CalcTot  ;

3

在同一张表中更新:

  DECLARE @TB1 TABLE
    (
        No Int
        ,Name NVarchar(50)
        ,linkNo int
    )

    DECLARE @TB2 TABLE
    (
        No Int
        ,Name NVarchar(50)
        ,linkNo int
    )

    INSERT INTO @TB1 VALUES(1,'changed person data',  0);
    INSERT INTO @TB1 VALUES(2,'old linked data of person', 1);

INSERT INTO @TB2 SELECT * FROM @TB1 WHERE linkNo = 0


SELECT * FROM @TB1
SELECT * FROM @TB2


    UPDATE @TB1 
        SET Name = T2.Name
    FROM        @TB1 T1
    INNER JOIN  @TB2 T2 ON T2.No = T1.linkNo

    SELECT * FROM @TB1

3

以下有人建议的SQL,在SQL Server中不起作用。这种语法让我想起了我的老班:

UPDATE table2 
SET table2.col1 = table1.col1, 
table2.col2 = table1.col2,
...
FROM table1, table2 
WHERE table1.memberid = table2.memberid

不建议使用NOT INNOT EXISTS进行其他所有查询。因为OP将整个数据集与较小的子集进行比较,所以会出现NULL,那么当然会出现匹配问题。必须使用正确的SQL编写正确的SQL JOIN来解决此问题,而不是使用来规避问题NOT IN。你可能会使用遇到其他问题,NOT IN或者NOT EXISTS在这种情况下。

我投票赞成最高的投票,这是通过加入SQL Server基于另一张表更新表的常规方式。就像我说的那样,UPDATE除非先连接它们,否则您不能在SQL Server的同一语句中使用两个表。


2
我只能说在SQL Server 2017中可以很好地工作。就像对未来的人的说明。无需加入。
SharpShade

3

它适用于PostgreSQL

UPDATE application
SET omts_received_date = (
    SELECT
        date_created
    FROM
        application_history
    WHERE
        application.id = application_history.application_id
    AND application_history.application_status_id = 8
);

1

我以为这是一个简单的例子,也许有人会变得更轻松,

        DECLARE @TB1 TABLE
        (
            No Int
            ,Name NVarchar(50)
        )

        DECLARE @TB2 TABLE
        (
            No Int
            ,Name NVarchar(50)
        )

        INSERT INTO @TB1 VALUES(1,'asdf');
        INSERT INTO @TB1 VALUES(2,'awerq');


        INSERT INTO @TB2 VALUES(1,';oiup');
        INSERT INTO @TB2 VALUES(2,'lkjhj');

        SELECT * FROM @TB1

        UPDATE @TB1 SET Name =S.Name
        FROM @TB1 T
        INNER JOIN @TB2 S
                ON S.No = T.No

        SELECT * FROM @TB1

0

甲骨文11g

merge into Sales_Import
using RetrieveAccountNumber
on (Sales_Import.LeadId = RetrieveAccountNumber.LeadId)
when matched then update set Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber;

-1

这将允许您基于在另一个表中找不到的列值来更新表。

    UPDATE table1 SET table1.column = 'some_new_val' WHERE table1.id IN (
            SELECT * 
            FROM (
                    SELECT table1.id
                    FROM  table1 
                    LEFT JOIN table2 ON ( table2.column = table1.column ) 
                    WHERE table1.column = 'some_expected_val'
                    AND table12.column IS NULL
            ) AS Xalias
    )

这将基于两个表中找到的列值来更新表。

    UPDATE table1 SET table1.column = 'some_new_val' WHERE table1.id IN (
            SELECT * 
            FROM (
                    SELECT table1.id
                    FROM  table1 
                    JOIN table2 ON ( table2.column = table1.column ) 
                    WHERE table1.column = 'some_expected_val'
            ) AS Xalias
    )

-1

尝试这个 :

UPDATE
    Table_A
SET
    Table_A.AccountNumber = Table_B.AccountNumber ,
FROM
    dbo.Sales_Import AS Table_A
    INNER JOIN dbo.RetrieveAccountNumber AS Table_B
        ON Table_A.LeadID = Table_B.LeadID 
WHERE
    Table_A.LeadID = Table_B.LeadID

-2

我想补充一件事。

不要使用相同的值更新值,它会产生额外的日志记录和不必要的开销。参见下面的示例-尽管链接到3,它仅对2条记录执行更新。

DROP TABLE #TMP1
DROP TABLE #TMP2
CREATE TABLE #TMP1(LeadID Int,AccountNumber NVarchar(50))
CREATE TABLE #TMP2(LeadID Int,AccountNumber NVarchar(50))

INSERT INTO #TMP1 VALUES
(147,'5807811235')
,(150,'5807811326')
,(185,'7006100100007267039');

INSERT INTO #TMP2 VALUES
(147,'7006100100007266957')
,(150,'7006100100007267039')
,(185,'7006100100007267039');

UPDATE A
SET A.AccountNumber = B.AccountNumber
FROM
    #TMP1 A 
        INNER JOIN #TMP2 B
        ON
        A.LeadID = B.LeadID
WHERE
    A.AccountNumber <> B.AccountNumber  --DON'T OVERWRITE A VALUE WITH THE SAME VALUE

SELECT * FROM #TMP1

-3

如果以上答案对您不起作用,请尝试此

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.