Aggiornamento SQL da una tabella all'altra in base a una corrispondenza ID


929

Ho un database con account numberse card numbers. Abbino questi a un file a updatequalsiasi numero di carta al numero di conto, in modo da lavorare solo con i numeri di conto.

Ho creato una vista che collega la tabella al database di account / carta per restituire il Table IDrelativo numero di account e ora devo aggiornare quei record in cui l'ID corrisponde al numero di account.

Questa è la Sales_Importtabella, in cui il account numbercampo deve essere aggiornato:

LeadID  AccountNumber
147         5807811235
150         5807811326
185         7006100100007267039

E questa è la RetrieveAccountNumbertabella, dove devo aggiornare da:

LeadID  AccountNumber
147         7006100100007266957
150         7006100100007267039

Ho provato il seguito, ma finora non ho avuto fortuna:

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

Aggiorna i numeri delle carte in numeri di conto, ma i numeri di conto vengono sostituiti da NULL

Risposte:


1369

Credo che una UPDATE FROMcon un JOINaiuto volontà:

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

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

18
Potresti voler usare l'alias di tabella nella clausola UPDATE, altrimenti causerà problemi se ti unisci alla tabella in qualsiasi momento.
Tom H,

15
Nella clausola set dovresti cambiare SI.AccountNumberin caso AccountNumbercontrario fallirà.
AaronLS

1
MS-Access utilizza un AGGIORNAMENTO diverso con l'istruzione JOIN. Dai
Christian Ammer,

92
questo sembra andare bene per mssql ma non sembra funzionare in mysql. Questo sembra fare il lavoro però: UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;. Leggermente fuori tema ma può essere utile
Edd,

7
Penso che non sia necessario il join interno. Soluzione Vonki seguito opere: UPDATE [Sales_Lead] [dbo] [Sales_Import] SET [AccountNumber] = RetrieveAccountNumber.AccountNumber FROM WHERE RetrieveAccountNumber [Sales_Lead] [dbo] [Sales_Import] = .LeadID RetrieveAccountNumber.LeadID....
Gutti

289

Il modo semplice per copiare il contenuto da una tabella all'altra è il seguente:

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

È inoltre possibile aggiungere la condizione per copiare i dati particolari.


2
Funziona, ma non hai bisogno di table2 in FROM UPDATE table2 SET table2.col1 = table1.col1, table2.col2 = table1.col2, ... DA table1 WHERE table1.memberid = table2.memberid
Sirentec

2
Questo non ha funzionato, ma AGGIORNAMENTO table2, table1 SET table2.col1 = table1.col1, ... DOVE table1.memberid = table2.memberid (mysql e phpmyadmin)
Tom Kuschel

156

Per SQL Server 2008 + L'uso MERGEpiuttosto che la UPDATE ... FROMsintassi proprietaria ha un certo fascino.

Oltre ad essere SQL standard e quindi più portabile genererà anche un errore nel caso in cui vi siano più righe unite sul lato sorgente (e quindi più possibili valori diversi da utilizzare nell'aggiornamento) piuttosto che avere il risultato finale essere indeterminato .

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

Sfortunatamente la scelta di quale usare potrebbe non scendere puramente allo stile preferito comunque. L'implementazione di MERGEin SQL Server è stata affetta da vari bug. Aaron Bertrand ha compilato un elenco di quelli riportati qui .


11
Heads up per MERGE.
Jakub Januszkiewicz,

2
Non ho mai saputo della sintassi di unione. È molto più pulito di Update + Join.
Tony Ashworth,

+1 per la segnalazione dell'implementazione di MERGE SQL Server
AFract

1
Gli argomenti per l'utilizzo di MERGE (compresi quelli nel post di sqlblog.com collegato sopra) potrebbero essere convincenti, ma una cosa da considerare potrebbe essere che secondo MSDN : ... L'istruzione MERGE funziona meglio quando le due tabelle hanno una combinazione complessa di caratteristiche corrispondenti ... Quando si aggiorna semplicemente una tabella in base alle righe di un'altra tabella, è possibile ottenere prestazioni e scalabilità migliorate con le istruzioni INSERT, UPDATE e DELETE di base
Tony Pulokas,

1
@ jkp1187 Questa domanda è taggata SQL Server. Quindi RE: FWIW - circa zero.
Martin Smith,

104

Risposta generica per i futuri sviluppatori.

server SQL

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

Oracle (e 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
Da notare almeno per SQL Server, utilizzare l'alias anziché il nome della tabella nella clausola di aggiornamento superiore ( update t1...anziché update Table1...)
gordon

2
La versione Oracle non funziona. Ottenere ORA-00933
ka3ak il

35

Per PostgreSQL:

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

34

Sembra che tu stia usando MSSQL, quindi, se ricordo bene, è fatto così:

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

33

Ho avuto lo stesso problema con foo.newl'impostazione su nullper le righe fooche non avevano una chiave corrispondente bar. Ho fatto qualcosa del genere in Oracle:

aggiorna foo
set foo.new = (seleziona bar.new
                  dal bar 
                  dove foo.key = bar.key)
dove esiste (selezionare 1
              dal bar
              dove foo.key = bar.key)

4
Perché è richiesto WHERE EXISTS ?
Georg Schölly,

6
Perché ogni riga in foo che non ha una corrispondenza nella barra è risultata nulla, poiché l'istruzione select ha prodotto null. Spero che questo sia stato più chiaro del mio primo tentativo di spiegarlo.
Kjell Andreassen,


@KjellAndreassen Hai risolto il mio problema. Grazie per il tuo codice
Bhavin Thummar,

27

Per MySql che funziona bene:

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

26

Ecco cosa ha funzionato per me in SQL Server:

UPDATE [AspNetUsers] SET

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

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

18

Grazie per le risposte Ho trovato una soluzione però.

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
Se il codice qui funziona o meno, dovresti probabilmente guardare le altre due soluzioni pubblicate. Sono molto più chiari e molto meno inclini all'errore e quasi sicuramente più veloci.
Tom H,

3
Solo una nota su questa soluzione, UPDATE ... FROM è proprietaria quindi, se non è possibile utilizzare l'istruzione MERGE perché si utilizza SQL 2005 o versioni precedenti, si tratta di un metodo conforme ANSI per eseguire gli aggiornamenti con un'origine tabella in MSSQL. Fonte: sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/…
pseudocoder

1
l'unica soluzione che funziona per me perché è un'istruzione di aggiornamento SQL standard (UPDATE SET WHERE), grazie
mille

13

Nel caso in cui le tabelle si trovino in database diversi. (MSSQL)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

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

10

Utilizzare il seguente blocco di query per aggiornare Table1 con Table2 in base all'ID:

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

Questo è il modo più semplice per affrontare questo problema.


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

aggiornamento all'interno della stessa tabella:

  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

Il seguente SQL suggerito da qualcuno, NON funziona in SQL Server. Questa sintassi mi ricorda la mia lezione di vecchia scuola:

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

Tutte le altre query che utilizzano NOT INo NOT EXISTSnon sono consigliate. I NULL vengono visualizzati perché OP confronta l'intero set di dati con un sottoinsieme più piccolo, quindi ovviamente ci sarà un problema di corrispondenza. Questo deve essere risolto scrivendo SQL corretto con il JOINproblema corretto invece di schivare usando NOT IN. È possibile riscontrare altri problemi utilizzando NOT INoNOT EXISTS in questo caso.

Il mio voto per quello in alto, che è il modo convenzionale di aggiornare una tabella basata su un'altra tabella unendo SQL Server. Come ho detto, non è possibile utilizzare due tabelle nella stessa UPDATEistruzione in SQL Server se non le si unisce prima.


2
Posso solo dire che in SQL Server 2017 funziona perfettamente. Proprio come una nota per le persone che verranno. Non c'è bisogno di unirsi a loro.
SharpShade,

3

funziona con 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

Pensavo che questo fosse un semplice esempio che qualcuno potrebbe ottenere più facilmente,

        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

Ciò ti consentirà di aggiornare una tabella in base al valore della colonna non presente in un'altra tabella.

    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
    )

Ciò aggiornerà una tabella in base al valore della colonna trovato in entrambe le tabelle.

    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

prova questo :

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

Vorrei aggiungere un'altra cosa.

Non aggiornare un valore con lo stesso valore, genera una registrazione aggiuntiva e un sovraccarico non necessario. Vedi l'esempio seguente: eseguirà l'aggiornamento solo su 2 record nonostante il collegamento su 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

Se le risposte sopra non funzionano per te, prova questo

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.