Atualização do SQL de uma tabela para outra com base em uma correspondência de ID

929

Eu tenho um banco de dados com account numberse card numbers. Eu os associo a um arquivo a updatequalquer número de cartão e ao número da conta, para que eu esteja trabalhando apenas com os números da conta.

Criei uma visualização vinculando a tabela ao banco de dados da conta / cartão para retornar o Table IDnúmero da conta e o respectivo, e agora preciso atualizar os registros em que o ID corresponde ao número da conta.

Esta é a Sales_Importtabela, na qual o account numbercampo precisa ser atualizado:

LeadID  AccountNumber
147         5807811235
150         5807811326
185         7006100100007267039

E esta é a RetrieveAccountNumbertabela, da qual preciso atualizar:

LeadID  AccountNumber
147         7006100100007266957
150         7006100100007267039

Eu tentei o abaixo, mas sem sorte até agora:

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

Ele atualiza os números de cartão para números de conta, mas os números de conta são substituídos por NULL

DineshDB
fonte

Respostas:

1369

Eu acredito que um UPDATE FROMcom um JOINajudará:

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;
Mark S. Rasmussen
fonte
18
Você pode usar o alias da tabela na cláusula UPDATE, caso contrário, causará problemas se você ingressar na tabela a qualquer momento.
Tom H
15
Na cláusula set, você deve alterar SI.AccountNumberpara o AccountNumbercontrário, falhará.
precisa saber é o seguinte
1
O MS-Access usa uma atualização diferente com a instrução JOIN. Dê uma olhada em: sql-und-xml.de/sql-tutorial/…
Christian Ammer
92
isso parece ser bom para o mssql, mas não parece funcionar no mysql. Isto parece fazer o trabalho que: UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;. Ligeiramente off topic, mas pode ser útil
Edd
7
Eu acho que não há necessidade da junção interna. A solução Vonki abaixo funciona: UPDATE [Sales_Lead]. [Dbo]. [Sales_Import] SET [AccountNumber] = RetrieveAccountNumber.AccountNumber FROM RetrieveAccountNumber WHERE [Sales_Lead]. [Dbo]. [Sales_Import] .LeadID = RetrieveAccountNumber.LeadID
Gutti em
289

A maneira simples de copiar o conteúdo de uma tabela para outra é a seguinte:

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

Você também pode adicionar a condição para obter os dados específicos copiados.

Shivkant
fonte
2
Isso funciona, mas você não precisa de table2 no FROM UPDATE table2 SET table2.col1 = table1.col1, table2.col2 = table1.col2, ... FROM table1 WHERE table1.memberid = table2.memberid
Sirentec
2
Isso não funcionou, mas table2 UPDATE, table1 SET table2.col1 = table1.col1, ... WHERE table1.memberid = table2.memberid (mysql e phpmyadmin)
Tom Kuschel
156

Para SQL Server 2008 + O uso, MERGEem vez da UPDATE ... FROMsintaxe proprietária, tem algum apelo.

Além de ser SQL padrão e, portanto, mais portátil, também gera um erro no caso de haver várias linhas unidas no lado da origem (e, portanto, vários valores diferentes possíveis para usar na atualização), em vez de ter o resultado final indeterminado .

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

Infelizmente, a escolha de qual usar pode não se resumir apenas ao estilo preferido. A implementação MERGEno SQL Server foi afetada por vários bugs. Aaron Bertrand compilou uma lista dos relatados aqui .

Martin Smith
fonte
11
Atenção MERGE.
Jakub Januszkiewicz
2
Eu nunca soube da sintaxe de mesclagem. É muito mais limpo que o Update + Join.
Tony Ashworth
+1 para relatar a implementação do MERGE SQL Server
AFract 6/13/13
1
Os argumentos para usar MERGE (incluindo os da publicação de sqlblog.com vinculados acima) podem ser convincentes, mas uma coisa a considerar pode ser que, de acordo com o MSDN : ... A instrução MERGE funcione melhor quando as duas tabelas tiverem uma mistura complexa de características combinando ... Quando simplesmente atualizando uma tabela com base nas linhas de outra tabela, melhor desempenho e escalabilidade podem ser alcançados com INSERT básico, UPDATE, e instruções DELETE
Tony Pulokas
1
@ jkp1187 Esta pergunta está marcada com o SQL Server. Então, RE: FWIW - aproximadamente zero.
Martin Smith
104

Resposta genérica para futuros desenvolvedores.

servidor 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;
Tigerjz32
fonte
2
De nota, pelo menos para o SQL Server, use o alias em vez do nome da tabela na cláusula de atualização superior ( update t1...em vez de update Table1...)
gordon
2
A versão Oracle não funciona. Obtendo ORA-
00933
35

Para o PostgreSQL:

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

Parece que você está usando o MSSQL, então, se bem me lembro, é feito assim:

UPDATE [Sales_Lead].[dbo].[Sales_Import] SET [AccountNumber] = 
RetrieveAccountNumber.AccountNumber 
FROM RetrieveAccountNumber 
WHERE [Sales_Lead].[dbo].[Sales_Import].LeadID = RetrieveAccountNumber.LeadID
Vinko Vrsalovic
fonte
33

Eu tive o mesmo problema ao foo.newser definido como nullpara linhas fooque não tinham chave correspondente bar. Eu fiz algo parecido com isto no Oracle:

update foo
set foo.new = (selecione bar.new
                  do bar 
                  onde foo.key = bar.key)
onde existe (selecione 1
              do bar
              onde foo.key = bar.key)
Kjell Andreassen
fonte
4
Por que o WHERE EXISTS é necessário?
Georg Schölly
6
Como cada linha no foo que não possui uma correspondência na barra acabou sendo nula, porque a instrução select produziu nulo. Espero que isso seja mais claro do que minha primeira tentativa de explicá-lo.
Kjell Andreassen
verifique esta resposta abaixo stackoverflow.com/questions/224732/…
Basheer AL-MOMANI
@KjellAndreassen Você resolveu o meu problema. Obrigado pelo seu código.
Bhavin Thummar 13/02/19
27

Para o MySql que funciona bem:

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

Aqui está o que funcionou para mim no SQL Server:

UPDATE [AspNetUsers] SET

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

FROM [AspNetUsers], [UserProfile]
WHERE [AspNetUsers].[Id] = [UserProfile].[Id];
Abhimanyu
fonte
18

Obrigado pelas respostas. Eu encontrei uma solução 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)  
Martin Smith
fonte
17
Se o código aqui funciona ou não, você provavelmente deve examinar as outras duas soluções postadas. Eles são muito mais claros e muito menos propensos a erros, além de quase certamente mais rápidos.
Tom H
3
Apenas uma observação sobre esta solução, UPDATE ... FROM é proprietária, portanto, se você não puder usar a instrução MERGE porque está usando o SQL 2005 ou anterior, este é um método compatível com ANSI para executar atualizações com uma fonte de tabela no MSSQL. Fonte: sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/…
pseudocoder
1
a única solução que funciona para mim porque é uma instrução de atualização SQL padrão (SET UPDATE WHERE), muito obrigado
Basheer AL-Momani
13

Caso as tabelas estejam em bancos de dados diferentes. (MSSQL)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

FROM database1..Ciudad c1
 inner join 
  database2..Ciudad c2 on c2.CiudadID=c1.CiudadID
Maurico Bello
fonte
10

Use o seguinte bloco de consulta para atualizar a Tabela1 com a Tabela2 com base no ID:

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

Essa é a maneira mais fácil de resolver esse problema.

Gil Baggio
fonte
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  ;
salman samadi
fonte
3

atualizar dentro da mesma tabela:

  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
NCP
fonte
3

O SQL abaixo sugerido por alguém NÃO funciona no SQL Server. Essa sintaxe me lembra minha turma da velha escola:

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

Todas as outras consultas que usam NOT INou NOT EXISTSnão são recomendadas. Os NULLs aparecem porque o OP compara um conjunto de dados inteiro com um subconjunto menor e, é claro, haverá um problema de correspondência. Isso deve ser corrigido escrevendo o SQL apropriado com o JOINproblema correto, em vez de desviar usando NOT IN. Você pode encontrar outros problemas usando NOT INou NOT EXISTSneste caso.

Meu voto na primeira, que é a maneira convencional de atualizar uma tabela com base em outra tabela, ingressando no SQL Server. Como eu disse, você não pode usar duas tabelas na mesma UPDATEinstrução no SQL Server, a menos que se junte a elas primeiro.

Dr Inner Join
fonte
2
Só posso dizer que no SQL Server 2017 isso funciona perfeitamente. Apenas como uma nota para as pessoas que estão chegando. Não há necessidade de se juntar a eles.
SharpShade
3

trabalha com 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
);
jakentus
fonte
1

Eu pensei que este é um exemplo simples, alguém pode ficar mais fácil,

        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
user824910
fonte
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;
Bruno
fonte
-1

Isso permitirá que você atualize uma tabela com base no valor da coluna não encontrado em outra tabela.

    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
    )

Isso atualizará uma tabela com base no valor da coluna sendo encontrado nas duas tabelas.

    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
    )
CG_DEV
fonte
-1

tente isto:

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
Oriel.F
fonte
-2

Eu gostaria de adicionar uma coisa extra.

Não atualize um valor com o mesmo valor, pois gera log extra e sobrecarga desnecessária. Veja o exemplo abaixo - ele fará a atualização apenas em 2 registros, apesar de vincular em 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
pacificamente
fonte
-3

Se as respostas acima não funcionarem para você, tente isso

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 
Shaw
fonte