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

คำตอบ:


1369

ฉันเชื่อUPDATE FROMด้วยความJOINประสงค์:

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 มิฉะนั้นจะทำให้เกิดปัญหาหากคุณเข้าร่วมตารางด้วยตนเองทุกจุด
Tom H

15
ในประโยคที่ตั้งไว้คุณควรเปลี่ยนSI.AccountNumberเป็นAccountNumberมิฉะนั้นจะล้มเหลว
AaronLS

1
MS-Access ใช้ UPDATE อื่นกับคำสั่ง JOIN ลองดูที่: sql-und-xml.de/sql-tutorial/ …
Christian Ammer

92
สิ่งนี้ดูเหมือนจะใช้ได้สำหรับ mssql แต่ดูเหมือนจะไม่ทำงานใน mysql UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;นี้ดูเหมือนว่าจะทำผลงานได้แม้ว่า: ปิดหัวข้อเล็กน้อย แต่อาจมีประโยชน์
Edd

7
ฉันคิดว่าไม่จำเป็นต้องเข้าร่วมวงใน วิธีการแก้ปัญหาด้านล่าง Vonki งาน: UPDATE [Sales_Lead] [dbo] [Sales_Import] SET [AccountNumber] = RetrieveAccountNumber.AccountNumber จาก RetrieveAccountNumber WHERE [Sales_Lead] [dbo] [Sales_Import] .LeadID = RetrieveAccountNumber.LeadID....
Gutti

289

วิธีง่ายๆในการคัดลอกเนื้อหาจากตารางหนึ่งไปยังอีกตารางหนึ่งมีดังนี้:

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

นอกจากนี้คุณยังสามารถเพิ่มเงื่อนไขเพื่อคัดลอกข้อมูลเฉพาะ


2
ใช้งานได้ แต่คุณไม่จำเป็นต้องใช้ table2 ในชุด FROM UPDATE table2 SET2 table1.col1 = table1.col1, table2.col2 = table1.col2, ... จาก table1 WHERE table1.memberid = table2.memberid
Sirentec

2
สิ่งนี้ใช้งานไม่ได้ แต่อัปเดต 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 ได้รับผลกระทบกับข้อบกพร่องต่าง ๆ แอรอนเบอร์ทรานด์ได้รวบรวมรายชื่อของคนที่รายงานที่นี่


11
มุ่งหน้าMERGEไป
Jakub Januszkiewicz

2
ฉันไม่เคยรู้เกี่ยวกับไวยากรณ์การรวม มันสะอาดกว่า Update + Join มาก
Tony Ashworth

+1 สำหรับการรายงานการนำ MERGE SQL Server ไปใช้งาน
หยุด

1
อาร์กิวเมนต์สำหรับการใช้ MERGE (รวมถึงการโพสต์จาก sqlblog.comลิงก์ด้านบน) อาจจะน่าสนใจ แต่สิ่งหนึ่งที่ควรพิจารณาอาจเป็นไปตาม MSDN : ... คำสั่ง MERGE ทำงานได้ดีที่สุดเมื่อทั้งสองตารางมีส่วนผสมที่ซับซ้อนของ ลักษณะการจับคู่ ... เมื่อทำการอัปเดตหนึ่งตารางโดยอิงตามแถวของตารางอื่นการปรับปรุงประสิทธิภาพและความสามารถในการปรับขยายสามารถทำได้ด้วยคำสั่ง INSERT, UPDATE และ DELETE ขั้นพื้นฐาน
Tony Pulokas

1
@ jkp1187 คำถามนี้ถูกติดแท็ก SQL Server ดังนั้น RE: FWIW - ประมาณศูนย์
Martin Smith

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 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การตั้งค่าnullสำหรับแถวของfooที่ไม่มีคีย์ที่ตรงกันbarที่มีคีย์ที่ตรงกับที่ในฉันทำสิ่งนี้ใน Oracle:

อัพเดต foo
set foo.new = (เลือก bar.new
                  จากแถบ 
                  โดยที่ foo.key = bar.key)
ที่มีอยู่ (เลือก 1
              จากแถบ
              โดยที่ foo.key = bar.key)

4
ทำไมWHERE EXISTSต้อง?
Georg Schölly

6
เนื่องจากแต่ละแถวใน foo ไม่มีการจับคู่ในแถบจบลงเป็นโมฆะเนื่องจากคำสั่ง select สร้าง null หวังว่านี่จะชัดเจนกว่าครั้งแรกที่ฉันพยายามอธิบาย
Kjell Andreassen

ตรวจสอบคำตอบนี้ด้านล่างstackoverflow.com/questions/224732/ …
Basheer AL-MOMANI

@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
ไม่ว่ารหัสที่นี่ใช้งานได้หรือไม่คุณควรดูที่อีกสองโซลูชันที่โพสต์ พวกเขามีความชัดเจนมากขึ้นและมีแนวโน้มที่จะเกิดข้อผิดพลาดน้อยลงและเร็วขึ้นอย่างแน่นอน
Tom H

3
เพียงหมายเหตุเกี่ยวกับโซลูชันนี้อัปเดต ... FROM เป็นกรรมสิทธิ์ดังนั้นหากคุณไม่สามารถใช้คำสั่ง MERGE ได้เนื่องจากคุณใช้ SQL 2005 หรือเก่ากว่านี่เป็นวิธีที่สอดคล้องกับมาตรฐาน ANSI ในการดำเนินการอัปเดตด้วยแหล่งตารางใน MSSQL ที่มา: sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10//
pseudocoder

1
ทางออกเดียวที่เหมาะกับฉันเพราะมันเป็นคำสั่งอัปเดต SQL มาตรฐาน (ตั้งค่าอัพเดตที่ไหน) ขอบคุณมาก
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

ใช้บล็อกของแบบสอบถามเพื่อปรับปรุง Table1 ด้วย Table2 ตาม ID:

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

นี่เป็นวิธีที่ง่ายที่สุดในการแก้ไขปัญหานี้


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

อัปเดตภายในตารางเดียวกัน:

  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 INหรือNOT EXISTSไม่แนะนำ NULL แสดงขึ้นเนื่องจาก OP ทำการเปรียบเทียบชุดข้อมูลทั้งหมดกับชุดย่อยขนาดเล็กจากนั้นแน่นอนว่าจะมีปัญหาการจับคู่ นี้จะต้องได้รับการแก้ไขโดยการเขียน 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

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

สิ่งนี้จะช่วยให้คุณอัปเดตตารางตามค่าคอลัมน์ที่ไม่พบในตารางอื่น

    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

ฉันต้องการเพิ่มสิ่งพิเศษ

อย่าอัปเดตค่าด้วยค่าเดียวกันมันสร้างการบันทึกพิเศษและค่าใช้จ่ายที่ไม่จำเป็น ดูตัวอย่างด้านล่าง - มันจะทำการอัพเดตใน 2 รายการเท่านั้นแม้จะมีการเชื่อมโยงกับ 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

หากคำตอบข้างต้นไม่ทำงานสำหรับคุณลองนี้

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.