SQL-Aktualisierung von einer Tabelle in eine andere basierend auf einer ID-Übereinstimmung


929

Ich habe eine Datenbank mit account numbersund card numbers. Ich ordne diese einer Datei mit updatebeliebigen Kartennummern der Kontonummer zu, so dass ich nur mit Kontonummern arbeite.

Ich habe eine Ansicht erstellt, die die Tabelle mit der Konto- / Kartendatenbank verknüpft, um die Table IDund die zugehörige Kontonummer zurückzugeben. Jetzt muss ich die Datensätze aktualisieren, bei denen die ID mit der Kontonummer übereinstimmt.

Dies ist die Sales_ImportTabelle, in der das account numberFeld aktualisiert werden muss:

LeadID  AccountNumber
147         5807811235
150         5807811326
185         7006100100007267039

Und dies ist die RetrieveAccountNumberTabelle, von der aus ich aktualisieren muss:

LeadID  AccountNumber
147         7006100100007266957
150         7006100100007267039

Ich habe das Folgende versucht, aber bisher kein Glück:

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

Die Kartennummern werden auf Kontonummern aktualisiert, die Kontonummern werden jedoch durch ersetzt NULL

Antworten:


1369

Ich glaube ein UPDATE FROMmit einem JOINWillen helfen:

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 und MariaDB

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

18
Möglicherweise möchten Sie den Tabellenalias in der UPDATE-Klausel verwenden, da dies sonst zu Problemen führen kann, wenn Sie sich zu irgendeinem Zeitpunkt selbst der Tabelle anschließen.
Tom H

15
In der set-Klausel sollten Sie zu ändern SI.AccountNumber, AccountNumbersonst schlägt es fehl.
AaronLS

1
MS-Access verwendet ein anderes UPDATE mit JOIN-Anweisung. Schauen Sie sich an: sql-und-xml.de/sql-tutorial/…
Christian Ammer

92
Dies scheint für mssql in Ordnung zu sein, scheint aber in mysql nicht zu funktionieren. Dies scheint jedoch die Aufgabe zu erfüllen : UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;. Etwas abseits des Themas, kann aber hilfreich sein
Edd

7
Ich denke, es besteht keine Notwendigkeit für die innere Verbindung. Vonki Lösung unter Arbeiten: UPDATE [Sales_Lead] [dbo] [Sales_Import] SET [Account] = RetrieveAccountNumber.AccountNumber FROM RetrieveAccountNumber WHERE [Sales_Lead] [dbo] [Sales_Import] .LeadID = RetrieveAccountNumber.LeadID....
Gutti

289

Der einfache Weg, den Inhalt von einer Tabelle in eine andere zu kopieren, ist wie folgt:

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

Sie können auch die Bedingung hinzufügen, um die bestimmten Daten zu kopieren.


2
Dies funktioniert, aber Sie benötigen table2 nicht in FROM UPDATE table2 SET table2.col1 = table1.col1, table2.col2 = table1.col2, ... FROM table1 WHERE table1.memberid = table2.memberid
Sirentec

2
Dies hat nicht funktioniert, aber UPDATE table2, table1 SET table2.col1 = table1.col1, ... WHERE table1.memberid = table2.memberid (mysql und phpmyadmin)
Tom Kuschel

156

Für SQL Server 2008 + hat die Verwendung MERGEanstelle der proprietären UPDATE ... FROMSyntax einen gewissen Reiz.

Es ist nicht nur Standard-SQL und damit portabler, sondern führt auch zu einem Fehler, wenn auf der Quellseite mehrere verknüpfte Zeilen vorhanden sind (und somit mehrere mögliche unterschiedliche Werte für das Update verwendet werden müssen), anstatt dass das Endergebnis unbestimmt ist .

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

Leider hängt die Wahl der Verwendung möglicherweise nicht nur vom bevorzugten Stil ab. Die Implementierung von MERGEin SQL Server war mit verschiedenen Fehlern behaftet. Aaron Bertrand hat hier eine Liste der gemeldeten zusammengestellt .


11
Kopf hoch für MERGE.
Jakub Januszkiewicz

2
Ich wusste nie über die Zusammenführungssyntax Bescheid. Es ist so viel sauberer als Update + Join.
Tony Ashworth

+1 für die Meldung der Implementierung von MERGE SQL Server
AFract

1
Die Argumente für die Verwendung von MERGE (einschließlich der oben verlinkten in dem Beitrag von sqlblog.com ) mögen überzeugend sein, aber eine Sache, die zu berücksichtigen ist, könnte laut MSDN sein : ... Die MERGE-Anweisung funktioniert am besten, wenn die beiden Tabellen eine komplexe Mischung aus haben Übereinstimmende Eigenschaften ... Wenn Sie einfach eine Tabelle basierend auf den Zeilen einer anderen Tabelle aktualisieren, können Sie mit den grundlegenden Anweisungen INSERT, UPDATE und DELETE eine verbesserte Leistung und Skalierbarkeit erzielen
Tony Pulokas,

1
@ jkp1187 Diese Frage ist mit SQL Server gekennzeichnet. Also RE: FWIW - ungefähr Null.
Martin Smith

104

Allgemeine Antwort für zukünftige Entwickler.

SQL Server

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

Oracle (und 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
Zumindest für SQL Server ist zu beachten, dass der Alias ​​anstelle des Tabellennamens in der obersten Aktualisierungsklausel ( update t1...anstelle von update Table1...) verwendet wird
Gordon

2
Die Oracle-Version funktioniert nicht. Erhalten von ORA-00933
ka3ak

35

Für PostgreSQL:

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

34

Anscheinend verwenden Sie MSSQL. Wenn ich mich richtig erinnere, geschieht dies folgendermaßen:

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

33

Ich hatte das gleiche Problem mit foo.newder Einstellung nullfür Zeilen, für foodie kein passender Schlüssel vorhanden war bar. Ich habe so etwas in Oracle gemacht:

Update foo
setze foo.new = (wähle bar.new
                  von der Bar 
                  wo foo.key = bar.key)
wo vorhanden (wählen Sie 1
              von der Bar
              wo foo.key = bar.key)

4
Warum ist das WHERE EXISTS erforderlich?
Georg Schölly

6
Weil jede Zeile in foo, die keine Übereinstimmung in der Leiste hat, null ist, weil die select-Anweisung null erzeugt hat. Ich hoffe, das war klarer als mein erster Versuch, es zu erklären.
Kjell Andreassen

Überprüfen Sie diese Antwort unter stackoverflow.com/questions/224732/…
Basheer AL-MOMANI

@KjellAndreassen Du hast mein Problem gelöst. Danke für deinen Code.
Bhavin Thummar

27

Für MySql funktioniert das gut:

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

26

Folgendes hat bei mir in SQL Server funktioniert:

UPDATE [AspNetUsers] SET

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

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

18

Danke für die Antworten. Ich habe eine Lösung gefunden.

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
Unabhängig davon, ob der Code hier funktioniert oder nicht, sollten Sie sich wahrscheinlich die beiden anderen veröffentlichten Lösungen ansehen. Sie sind viel klarer und weniger fehleranfällig sowie mit ziemlicher Sicherheit schneller.
Tom H

3
Nur ein Hinweis zu dieser Lösung: UPDATE ... FROM ist proprietär. Wenn Sie die MERGE-Anweisung nicht verwenden können, weil Sie SQL 2005 oder früher verwenden, ist dies eine ANSI-kompatible Methode zum Durchführen von Aktualisierungen mit einer Tabellenquelle in MSSQL. Quelle: sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/…
Pseudocoder

1
Die einzige Lösung, die für mich funktioniert, weil es eine Standard-SQL-Update-Anweisung ist (UPDATE SET WHERE), vielen Dank
Basheer AL-MOMANI

13

Falls sich die Tabellen in einer anderen Datenbank befinden. (MSSQL)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

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

10

Verwenden Sie den folgenden Abfrageblock, um Tabelle1 mit Tabelle2 basierend auf der ID zu aktualisieren:

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

Dies ist der einfachste Weg , um dieses Problem anzugehen.


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

Update in derselben Tabelle:

  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

Das unten von jemandem vorgeschlagene SQL funktioniert NICHT in SQL Server. Diese Syntax erinnert mich an meine alte Schulklasse:

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

Alle anderen Abfragen mit NOT INoder NOT EXISTSwerden nicht empfohlen. NULL-Werte werden angezeigt, da OP den gesamten Datensatz mit einer kleineren Teilmenge vergleicht. Dann tritt natürlich ein Übereinstimmungsproblem auf. Dies muss behoben werden, indem korrektes SQL mit korrektem geschrieben wird, JOINanstatt dem Problem mit auszuweichen NOT IN. Bei Verwendung von NOT INoder NOT EXISTSin diesem Fall können andere Probleme auftreten .

Meine Stimme für die oberste, die herkömmliche Methode zum Aktualisieren einer Tabelle basierend auf einer anderen Tabelle durch Beitritt zu SQL Server ist. Wie ich bereits sagte, können Sie UPDATEin SQL Server nur dann zwei Tabellen in derselben Anweisung verwenden, wenn Sie sie zuerst verbinden.


2
Ich kann nur sagen, dass dies in SQL Server 2017 einwandfrei funktioniert. Nur als Hinweis für zukünftige Leute, die vorbeikommen. Keine Notwendigkeit, sich ihnen anzuschließen.
SharpShade

3

es funktioniert mit 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

Ich dachte, dies ist ein einfaches Beispiel, vielleicht könnte es jemand einfacher machen.

        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

Auf diese Weise können Sie eine Tabelle basierend auf dem Spaltenwert aktualisieren, der in einer anderen Tabelle nicht gefunden wurde.

    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
    )

Dadurch wird eine Tabelle basierend auf dem Spaltenwert aktualisiert, der in beiden Tabellen gefunden wird.

    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

Versuche dies :

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

Ich möchte noch etwas hinzufügen.

Aktualisieren Sie keinen Wert mit demselben Wert, da dies zu zusätzlicher Protokollierung und unnötigem Overhead führt. Siehe Beispiel unten - die Aktualisierung wird nur für 2 Datensätze durchgeführt, obwohl auf 3 verknüpft wird.

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

Wenn die obigen Antworten für Sie nicht funktionieren, versuchen Sie dies

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.