Cập nhật SQL từ Bảng này sang Bảng khác dựa trên đối sánh ID


929

Tôi có một cơ sở dữ liệu với account numberscard numbers. Tôi khớp chúng với một tệp với updatebất kỳ số thẻ nào với số tài khoản, do đó tôi chỉ làm việc với số tài khoản.

Tôi đã tạo chế độ xem liên kết bảng với cơ sở dữ liệu thẻ / tài khoản để trả về Table IDvà số tài khoản liên quan và bây giờ tôi cần cập nhật những hồ sơ mà ID khớp với Số tài khoản.

Đây là Sales_Importbảng, nơi account numbertrường cần được cập nhật:

LeadID  AccountNumber
147         5807811235
150         5807811326
185         7006100100007267039

Và đây là RetrieveAccountNumberbảng, nơi tôi cần cập nhật từ:

LeadID  AccountNumber
147         7006100100007266957
150         7006100100007267039

Tôi đã thử dưới đây, nhưng không có may mắn cho đến nay:

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

Nó cập nhật số thẻ thành số tài khoản, nhưng số tài khoản được thay thế bằng NULL

Câu trả lời:


1369

Tôi tin rằng UPDATE FROMmột JOINý chí sẽ giúp:

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 và MariaDB

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

18
Bạn có thể muốn sử dụng bí danh bảng trong mệnh đề CẬP NHẬT, nếu không nó sẽ gây ra vấn đề nếu bạn tự tham gia bảng bất cứ lúc nào.
Tom H

15
Trong mệnh đề tập hợp, bạn nên thay đổi SI.AccountNumberthành chỉ AccountNumbernếu không nó sẽ thất bại.
AaronLS

1
MS-Access sử dụng một CẬP NHẬT khác với Tuyên bố THAM GIA. Hãy xem: sql-und-xml.de/sql-tutorial/ Kẻ
Christian Ammer

92
điều này có vẻ tốt cho mssql nhưng dường như không hoạt động trong mysql. Điều này dường như để làm công việc mặc dù : UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;. Hơi lạc đề nhưng có thể hữu ích
Edd

7
Tôi nghĩ rằng không cần sự tham gia bên trong. Vonki giải pháp dưới đây tác phẩm: UPDATE [Sales_Lead] [dbo] [Sales_Import] SET [ACCOUNTNUMBER] = RetrieveAccountNumber.AccountNumber TỪ RetrieveAccountNumber ĐÂU [Sales_Lead] [dbo] [Sales_Import] .LeadID = RetrieveAccountNumber.LeadID....
Gutti

289

Cách đơn giản để sao chép nội dung từ bảng này sang bảng khác như sau:

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

Bạn cũng có thể thêm điều kiện để có được dữ liệu cụ thể được sao chép.


2
Điều này hoạt động, nhưng bạn không cần bảng2 trong bảng TỪ CẬP NHẬT2 SET bảng2.col1 = table1.col1, table2.col2 = table1.col2, ... TỪ bảng1 WHERE bảng1.memberid = table2.memberid
Sirentec

2
Điều này không làm việc, nhưng CẬP NHẬT table2, table1 SET table2.col1 = table1.col1, ... WHERE table1.memberid = table2.memberid (mysql và phpmyadmin)
Tom Kuschel

156

Đối với SQL Server 2008 + Sử dụng MERGEthay vì UPDATE ... FROMcú pháp độc quyền có một số kháng cáo.

Ngoài việc là SQL tiêu chuẩn và do đó dễ di chuyển hơn, nó cũng sẽ gây ra lỗi trong trường hợp có nhiều hàng được nối ở phía nguồn (và do đó, nhiều giá trị khác nhau có thể sử dụng trong bản cập nhật) thay vì không có kết quả cuối cùng là không xác định .

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

Thật không may, sự lựa chọn sử dụng có thể không hoàn toàn đi xuống phong cách ưa thích tuy nhiên. Việc triển khai MERGEtrong SQL Server đã bị ảnh hưởng bởi các lỗi khác nhau. Aaron Bertrand đã biên soạn một danh sách những người được báo cáo ở đây .


11
Đứng lên cho MERGE.
Jakub Januszkiewicz

2
Tôi không bao giờ biết về cú pháp hợp nhất. Nó sạch sẽ hơn nhiều so với Cập nhật + Tham gia.
Tony Ashworth

+1 để báo cáo về việc triển khai MERGE SQL Server
Thu thập

1
Các đối số để sử dụng MERGE (bao gồm cả các đối số trong bài đăng từ sqlblog.com được liên kết ở trên) có thể hấp dẫn, nhưng một điều cần xem xét có thể là theo MSDN : ... Câu lệnh MERGE hoạt động tốt nhất khi hai bảng có hỗn hợp phức tạp là các đặc điểm phù hợp ... Khi chỉ cần cập nhật một bảng dựa trên các hàng của một bảng khác, hiệu suất và khả năng mở rộng được cải thiện có thể đạt được bằng các câu lệnh INSERT, UPDATE và DELETE cơ bản
Tony Pulokas

1
@ jkp1187 Câu hỏi này được gắn thẻ SQL Server. Vậy RE: FWIW - xấp xỉ bằng không.
Martin Smith

104

Câu trả lời chung cho các nhà phát triển trong tương lai.

Máy chủ SQL

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

Oracle (và 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
Lưu ý ít nhất là đối với SQL Server, sử dụng bí danh thay vì tên bảng trong mệnh đề cập nhật hàng đầu ( update t1...chứ không phải update Table1...)
gordon

2
Phiên bản Oracle không hoạt động. Bắt ORA-00933
ka3ak

35

Đối với PostgreSQL:

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

34

Có vẻ như bạn đang sử dụng MSSQL, sau đó, nếu tôi nhớ chính xác, nó được thực hiện như sau:

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

33

Tôi gặp vấn đề tương tự với foo.newviệc được đặt thành nullcác hàng fookhông có khóa khớp bar. Tôi đã làm một cái gì đó như thế này trong Oracle:

cập nhật foo
đặt foo.new = (chọn bar.new
                  từ thanh 
                  trong đó foo.key = bar.key)
nơi tồn tại (chọn 1
              từ thanh
              trong đó foo.key = bar.key)

4
Tại sao cần phải có EXISTS ?
Georg Schölly

6
Bởi vì mỗi hàng trong foo không có kết quả khớp trong thanh kết thúc là null, vì câu lệnh select tạo ra null. Hy vọng điều này rõ ràng hơn nỗ lực đầu tiên của tôi trong việc giải thích nó.
Kjell Andreassen

kiểm tra câu trả lời dưới đây stackoverflow.com/questions/224732/ từ
Basheer AL-MOMANI

@KjellAndreassen Bạn đã giải quyết vấn đề của tôi. Cảm ơn mã của bạn.
Bhavin Thummar

27

Đối với MySql hoạt động tốt:

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

26

Đây là những gì làm việc cho tôi trong SQL Server:

UPDATE [AspNetUsers] SET

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

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

18

Cảm ơn các câu trả lời. Tôi tìm thấy một giải pháp tho.

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
Cho dù mã ở đây có hoạt động hay không, có lẽ bạn nên xem hai giải pháp khác được đăng. Chúng rõ ràng hơn và ít bị lỗi hơn cũng như gần như chắc chắn nhanh hơn.
Tom H

3
Do đó, chỉ cần lưu ý về giải pháp này, CẬP NHẬT ... TỪ là độc quyền, do đó, nếu bạn không thể sử dụng câu lệnh MERGE vì bạn đang sử dụng SQL 2005 trở về trước, đây là phương pháp thực hiện cập nhật ANSI theo nguồn bảng trong MSSQL. Nguồn: sqlblog.com/bloss/hugo_kornelis/archive/2008/03/10/ trên
giả

1
giải pháp duy nhất phù hợp với tôi vì đó là câu lệnh cập nhật SQL tiêu chuẩn (CẬP NHẬT
TẬP ĐOÀN

13

Trong trường hợp các bảng nằm trong một cơ sở dữ liệu khác nhau. (MSSQL)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

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

10

Sử dụng khối truy vấn sau để cập nhật Bảng 1 với Bảng 2 dựa trên ID:

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

Đây là cách dễ nhất để giải quyết vấn đề này.


8

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

Oracle 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

cập nhật trong cùng một bảng:

  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

Một số SQL dưới đây được đề xuất, KHÔNG hoạt động trong SQL Server. Cú pháp này làm tôi nhớ đến lớp học cũ của tôi:

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

Tất cả các truy vấn khác sử dụng NOT INhoặc NOT EXISTSkhông được khuyến khích. Các NULL xuất hiện vì OP so sánh toàn bộ tập dữ liệu với tập hợp con nhỏ hơn, nên dĩ nhiên sẽ có vấn đề khớp. Điều này phải được sửa bằng cách viết SQL đúng với JOINthay vì tránh vấn đề bằng cách sử dụng NOT IN. Bạn có thể gặp phải các vấn đề khác bằng cách sử dụng NOT INhoặc NOT EXISTStrong trường hợp này.

Phiếu bầu của tôi cho bảng hàng đầu, đó là cách cập nhật bảng thông thường dựa trên bảng khác bằng cách tham gia vào SQL Server. Giống như tôi đã nói, bạn không thể sử dụng hai bảng trong cùng một UPDATEcâu lệnh trong SQL Server trừ khi bạn tham gia chúng trước.


2
Tôi chỉ có thể nói rằng trong SQL Server 2017, điều này hoạt động hoàn toàn tốt. Cũng như một lưu ý cho những người tương lai đi qua. Không cần phải tham gia cùng họ.
SharpShade

3

nó hoạt động với 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

Tôi nghĩ rằng đây là một ví dụ đơn giản có thể ai đó sẽ dễ dàng hơn,

        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

Oracle 11g

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

-1

Điều này sẽ cho phép bạn cập nhật một bảng dựa trên giá trị cột không được tìm thấy trong một bảng khác.

    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
    )

Điều này sẽ cập nhật một bảng dựa trên giá trị cột được tìm thấy trong cả hai bảng.

    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

thử cái này :

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

Tôi muốn thêm một điều nữa.

Đừng cập nhật một giá trị có cùng giá trị, nó sẽ tạo thêm nhật ký và chi phí không cần thiết. Xem ví dụ dưới đây - nó sẽ chỉ thực hiện cập nhật trên 2 bản ghi mặc dù liên kết trên 3.

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

Nếu câu trả lời trên không hiệu quả với bạn hãy thử điều này

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.