关于sql server:基于ID匹配从一个表到另一个表的SQL更新

SQL update from one Table to another based on a ID match

我有一个account numberscard numbers的数据库。 我将这些文件与update的任何卡号匹配到帐号,这样我才能使用帐号。

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

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

1
2
3
4
LeadID  AccountNumber
147         5807811235
150         5807811326
185         7006100100007267039

这是RetrieveAccountNumber表,我需要更新:

1
2
3
LeadID  AccountNumber
147         7006100100007266957
150         7006100100007267039

我试过以下,但到目前为止没有运气:

1
2
3
4
5
UPDATE [Sales_Lead].[dbo].[Sales_Import]
SET    [AccountNumber] = (SELECT RetrieveAccountNumber.AccountNumber
                          FROM   RetrieveAccountNumber
                          WHERE  [Sales_Lead].[dbo].[Sales_Import]. LeadID =
                                                RetrieveAccountNumber.LeadID)

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


我相信带有JOINUPDATE FROM会有所帮助:

MS SQL

1
2
3
4
5
6
7
8
9
10
UPDATE
    Sales_Import
SET
    Sales_Import.AccountNumber = RAN.AccountNumber
FROM
    Sales_Import SI
INNER JOIN
    RetrieveAccountNumber RAN
ON
    SI.LeadID = RAN.LeadID;

MySQL和MariaDB

1
2
3
4
5
6
7
UPDATE
    Sales_Import SI,
    RetrieveAccountNumber RAN
SET
    SI.AccountNumber = RAN.AccountNumber
WHERE
    SI.LeadID = RAN.LeadID;


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

1
2
3
4
5
6
UPDATE table2
SET table2.col1 = table1.col1,
table2.col2 = table1.col2,
...
FROM table1, table2
WHERE table1.memberid = table2.memberid

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


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

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

1
2
3
4
5
6
MERGE INTO Sales_Import
   USING RetrieveAccountNumber
      ON Sales_Import.LeadID = RetrieveAccountNumber.LeadID
WHEN MATCHED THEN
   UPDATE
      SET AccountNumber = RetrieveAccountNumber.AccountNumber;

不幸的是,选择哪种使用可能不会纯粹归结为优选的风格。 SQL Server中MERGE的实现受到各种错误的影响。 Aaron Bertrand在这里编制了一份报告清单。


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

SQL Server

1
2
3
4
5
6
7
8
UPDATE
     t1
SET
     t1.column = t2.column
FROM
     Table1 t1
     INNER JOIN Table2 t2
     ON t1.id = t2.id;

Oracle(和SQL Server)

1
2
3
4
5
6
7
8
9
UPDATE
     t1
SET
     t1.colmun = t2.column
FROM
     Table1 t1,
     Table2 t2
WHERE
     t1.ID = t2.ID;

MySQL的

1
2
3
4
5
6
7
UPDATE
     Table1 t1,
     Table2 t2
SET
     t1.column = t2.column
WHERE
     t1.ID = t2.ID;


看来你正在使用MSSQL,如果我没记错的话,它是这样完成的:

1
2
3
4
UPDATE [Sales_Lead].[dbo].[Sales_Import] SET [AccountNumber] =
RetrieveAccountNumber.AccountNumber
FROM RetrieveAccountNumber
WHERE [Sales_Lead].[dbo].[Sales_Import].LeadID = RetrieveAccountNumber.LeadID

我有同样的问题,foo.new被设置为nullfoobar中没有匹配的键。我在Oracle中做了类似的事情:

1
2
3
4
5
6
7
UPDATE foo
SET    foo.new = (SELECT bar.new
                  FROM bar
                  WHERE foo.key = bar.key)
WHERE EXISTS (SELECT 1
              FROM bar
              WHERE foo.key = bar.key)


对于PostgreSQL:

1
2
3
4
UPDATE Sales_Import SI
SET AccountNumber = RAN.AccountNumber
FROM RetrieveAccountNumber RAN
WHERE RAN.LeadID = SI.LeadID;

对于工作正常的MySql:

1
2
3
4
5
6
UPDATE
    Sales_Import SI,RetrieveAccountNumber RAN
SET
    SI.AccountNumber = RAN.AccountNumber
WHERE
    SI.LeadID = RAN.LeadID

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

1
2
3
4
5
6
7
UPDATE [AspNetUsers] SET

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

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


谢谢你的回复。我发现了一个解决方案。

1
2
3
4
5
6
7
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)


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

1
2
3
UPDATE Sales_Import, RetrieveAccountNumber
SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber
WHERE Sales_Import.LeadID = RetrieveAccountNumber.LeadID;

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


以下SQL有人建议,在SQL Server中不起作用。这个语法让我想起了我的旧学校课程:

1
2
3
4
5
6
UPDATE table2
SET table2.col1 = table1.col1,
table2.col2 = table1.col2,
...
FROM table1, table2
WHERE table1.memberid = table2.memberid

建议不要使用NOT INNOT EXISTS的所有其他查询。由于OP将整个数据集与较小的子集进行比较,因此会显示NULL,然后会出现匹配问题。必须通过使用NOT IN编写正确的JOIN而不是避免问题的SQL来修复此问题。在这种情况下,您可能会使用NOT INNOT EXISTS来遇到其他问题。

我对顶级投票的投票,这是通过加入SQL Server来更新基于另一个表的表的传统方式。就像我说的,你不能在SQL Server中的同一个UPDATE语句中使用两个表,除非你先加入它们。


在同一个表中更新:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  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

它适用于postgresql

1
2
3
4
5
6
7
8
9
10
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
);


MS Sql

1
2
3
4
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';

Oracle 11g

1
2
3
4
5
6
7
8
9
10
11
12
        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  ;

我认为这是一个简单的例子可能有人会让它更容易,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        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

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

1
2
3
4
5
6
UPDATE database1..Ciudad
SET CiudadDistrito=c2.CiudadDistrito

FROM database1..Ciudad c1
 INNER JOIN
  database2..Ciudad c2 ON c2.CiudadID=c1.CiudadID

Oracle 11g

1
2
3
4
MERGE INTO Sales_Import
USING RetrieveAccountNumber
ON (Sales_Import.LeadId = RetrieveAccountNumber.LeadId)
WHEN matched THEN UPDATE SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber;

试试这个 :

1
2
3
4
5
6
7
8
9
10
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


这将允许您根据另一个表中找不到的列值更新表。

1
2
3
4
5
6
7
8
9
10
    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
    )

这将根据在两个表中找到的列值更新表。

1
2
3
4
5
6
7
8
9
    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
    )

我想补充一点。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

如果以上答案不适合你,试试这个

1
2
3
UPDATE Sales_Import A LEFT JOIN RetrieveAccountNumber B ON A.LeadID = B.LeadID
SET A.AccountNumber = B.AccountNumber
WHERE A.LeadID = B.LeadID