1234

I have a database with account numbers and card numbers. I match these to a file to update any card numbers to the account number so that I am only working with account numbers.

I created a view linking the table to the account/card database to return the Table ID and the related account number, and now I need to update those records where the ID matches the Account Number.

This is the Sales_Import table, where the account number field needs to be updated:

LeadID AccountNumber
147 5807811235
150 5807811326
185 7006100100007267039

And this is the RetrieveAccountNumber table, where I need to update from:

LeadID AccountNumber
147 7006100100007266957
150 7006100100007267039

I tried the below, but no luck so far:

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

It updates the card numbers to account numbers, but the account numbers get replaced by NULL

29 Answers 29

1741

I believe an UPDATE FROM with a JOIN will help:

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

UPDATE Sales_Import SI, RetrieveAccountNumber RAN SET SI.AccountNumber = RAN.AccountNumber WHERE SI.LeadID = RAN.LeadID; 
Sign up to request clarification or add additional context in comments.

12 Comments

You might want to use the table alias in the UPDATE clause, otherwise it will cause problems if you self join the table at any point.
In the set clause you should change SI.AccountNumber to just AccountNumber otherwise it will fail.
MS-Access uses a different UPDATE with JOIN Statement. Have a look at: sql-und-xml.de/sql-tutorial/…
this seems to be fine for mssql but doesn't seem to work in mysql. This seems to do the job though: UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;. Slightly off topic but may be helpful
I think there is no need for the inner join. Vonki solution below works: UPDATE [Sales_Lead].[dbo].[Sales_Import] SET [AccountNumber] = RetrieveAccountNumber.AccountNumber FROM RetrieveAccountNumber WHERE [Sales_Lead].[dbo].[Sales_Import].LeadID = RetrieveAccountNumber.LeadID
|
352

The simple Way to copy the content from one table to other is as follow:

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

You can also add the condition to get the particular data copied.

2 Comments

This works, but you don't need table2 in the FROM UPDATE table2 SET table2.col1 = table1.col1, table2.col2 = table1.col2, ... FROM table1 WHERE table1.memberid = table2.memberid
This didn't worked, but UPDATE table2, table1 SET table2.col1 = table1.col1, ... WHERE table1.memberid = table2.memberid (mysql and phpmyadmin)
174

For SQL Server 2008 + Using MERGE rather than the proprietary UPDATE ... FROM syntax has some appeal.

As well as being standard SQL and thus more portable it also will raise an error in the event of there being multiple joined rows on the source side (and thus multiple possible different values to use in the update) rather than having the final result be undeterministic.

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

Unfortunately the choice of which to use may not come down purely to preferred style however. The implementation of MERGE in SQL Server has been afflicted with various bugs. Aaron Bertrand has compiled a list of the reported ones here.

7 Comments

MERGE is great, but it's worth noting that it will not work if you're using a linked server The target of a MERGE statement cannot be a remote table, a remote view, or a view over remote tables..
The arguments for using MERGE (including those in the post from sqlblog.com linked above) might be compelling, but one thing to consider might be that according to MSDN: ...MERGE statement works best when the two tables have a complex mixture of matching characteristics...When simply updating one table based on the rows of another table, improved performance and scalability can be achieved with basic INSERT, UPDATE, and DELETE statements
I realize it's dated now, but the linked post from Bertrand says, "However, MERGE originally shipped with several "wrong results" and other bugs... some of which continue to exist even in the early preview releases of SQL Server 2014... I have been recommending that - for now - people stick to their tried and true methods of separate statements." (emph mine) See also his comment on January 26, 2014 - 8:28:58 PM. @MartinSmith -- Any reason to suspect things are better now?
FWIW, does not work with Access shipped with MS Office 365 Pro Plus.
@jkp1187 This question is tagged SQL Server. So RE: FWIW - approximately zero.
|
170

Generic answer for future developers.

SQL Server

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

Oracle (and 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; 

6 Comments

Of note at least for SQL Server, use the alias rather than the table name in the top update clause (update t1... rather than update Table1...)
Does not work in Oracle: ORA-00933: SQL command not properly ended
What is the suggested solution for ORA-00933?
the oracle variant did not work for me
The Oracle SQL answer is obviously wrong, you can only use Merge Into or correlated subquery to achieve this
|
82

For PostgreSQL:

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

1 Comment

The mistake which I am doing is: SET SI.AccountNumber = RAN.AccountNumber. Still, I wonder why it is wrong in postgresql? Can anyone explain?
43

Seems you are using MSSQL, then, if I remember correctly, it is done like this:

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

Comments

38

I had the same problem with foo.new being set to null for rows of foo that had no matching key in bar. I did something like this in Oracle:

 update foo set foo.new = (select bar.new from bar where foo.key = bar.key) where exists (select 1 from bar where foo.key = bar.key) 

3 Comments

Why is the WHERE EXISTS required?
Because each row in foo not having a match in bar ended up being null, because the select statement produced null. Hope this was clearer than my first attempt at explaining it.
38

Here's what worked for me in SQL Server:

UPDATE [AspNetUsers] SET [AspNetUsers].[OrganizationId] = [UserProfile].[OrganizationId], [AspNetUsers].[Name] = [UserProfile].[Name] FROM [AspNetUsers], [UserProfile] WHERE [AspNetUsers].[Id] = [UserProfile].[Id]; 

Comments

32

For MySql that works fine:

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

Comments

24

Thanks for the responses. I found a solution 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) 

3 Comments

Whether or not the code here works, you should probably look at the other two solutions posted. They are much clearer and much less prone to error as well as almost certainly faster.
Just a note on this solution, UPDATE...FROM is proprietary therefore, if you cannot use the MERGE statement because you are using SQL 2005 or earlier, this is an ANSI-compliant method of performing updates with a table source in MSSQL. Source: sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/…
the only solution that works for me because its a standard SQL update statement (UPDATE SET WHERE), thanks alot
21

In case the tables are in a different databases. (MSSQL)

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

Comments

18

Use the following block of query to update Table1 with Table2 based on ID:

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

This is the easiest way to tackle this problem.

1 Comment

This query is good, but until the development is done, it will block the whole table. can we make any change here, to convert it to a row-based lock only?
16

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 ; 

Comments

12

update from one table to another table on id matched

UPDATE TABLE1 t1, TABLE2 t2 SET t1.column_name = t2.column_name WHERE t1.id = t2.id; 

2 Comments

In SQL Server v18, it does not seem to allow a second table in the UPDATE. It complains about the comma and wants a SET statement. Perhaps this solution works in a different database.
On MariaDB and MySQL worked like a charm... it took its time but it searched over 18M records, but did it perfectly. Not only for ID, I used other variables as well such as WHERE t1.lastname = t2.lastname;
8

The below SQL someone suggested, does NOT work in SQL Server. This syntax reminds me of my old school class:

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

All other queries using NOT IN or NOT EXISTS are not recommended. NULLs show up because OP compares entire dataset with smaller subset, then of course there will be matching problem. This must be fixed by writing proper SQL with correct JOIN instead of dodging problem by using NOT IN. You might run into other problems by using NOT IN or NOT EXISTS in this case.

My vote for the top one, which is conventional way of updating a table based on another table by joining in SQL Server. Like I said, you cannot use two tables in same UPDATE statement in SQL Server unless you join them first.

1 Comment

I can only say that in SQL Server 2017 this works perfectly well. Just as a note for future people coming by. No need to join them.
8

Summarizing the other answers, there're 4 variants of how to update target table using data from another table only when "match exists"

Query and sub-query:

update si set si.AccountNumber = ( select ran.AccountNumber from RetrieveAccountNumber ran where si.LeadID = ran.LeadID ) from Sales_Import si where exists (select * from RetrieveAccountNumber ran where ran.LeadID = si.LeadID) 

Inner join:

update si set si.AccountNumber = ran.AccountNumber from Sales_Import si inner join RetrieveAccountNumber ran on si.LeadID = ran.LeadID 

Cross join:

update si set si.AccountNumber = ran.AccountNumber from Sales_Import si, RetrieveAccountNumber ran where si.LeadID = ran.LeadID 

Merge:

merge into Sales_Import si using RetrieveAccountNumber ran on si.LeadID = ran.LeadID when matched then update set si.accountnumber = ran.accountnumber; 

All variants are more-less trivial and understandable, personally I prefer "inner join" option. But any of them could be used and developer has to select "better option" according to his/her needs

From performance perspective variants with join-s are more preferable: enter image description here

1 Comment

Successfully used the cross join example. As the source was a backup and the tables had the same names I needed to use alias names but it worked beautifully then. Thanks!
7

This is the easiest and best have seen for Mysql and Maria DB

UPDATE table2, table1 SET table2.by_department = table1.department WHERE table1.id = table2.by_id 

Note: If you encounter the following error based on your Mysql/Maria DB version "Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode, toggle the option in Preferences"

Then run the code like this

SET SQL_SAFE_UPDATES=0; UPDATE table2, table1 SET table2.by_department = table1.department WHERE table1.id = table2.by_id 

Comments

5

it works with 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 ); 

Comments

4

update within the same table:

 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 

Comments

2

I thought this is a simple example might someone get it easier,

 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 

Comments

2

try this :

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 

Comments

2

MYSQL (This is my preferred way for restoring all specific column reasonId values, based on primary key id equivalence)

UPDATE `site` AS destination INNER JOIN `site_copy` AS backupOnTuesday ON backupOnTuesday.`id` = destination.`id` SET destdestination.`reasonId` = backupOnTuesday.`reasonId` 

Comments

2

This will allow you to update a table based on the column value not being found in another table.

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 ) 

This will update a table based on the column value being found in both tables.

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 ) 

Comments

1

Oracle 11g

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

Comments

1

For Oracle SQL try using alias

UPDATE Sales_Lead.dbo.Sales_Import SI SET SI.AccountNumber = (SELECT RAN.AccountNumber FROM RetrieveAccountNumber RAN WHERE RAN.LeadID = SI.LeadID); 

1 Comment

You answer seems the same as lot of others
0

I'd like to add one extra thing.

Don't update a value with the same value, it generates extra logging and unnecessary overhead. See example below - it will only perform the update on 2 records despite linking on 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 

Comments

0

ORACLE

use

UPDATE suppliers SET supplier_name = (SELECT customers.customer_name FROM customers WHERE customers.customer_id = suppliers.supplier_id) WHERE EXISTS (SELECT customers.customer_name FROM customers WHERE customers.customer_id = suppliers.supplier_id); 

Comments

0

update table1 dpm set col1 = dpu.col1 from table2 dpu where dpm.parameter_master_id = dpu.parameter_master_id;

Comments

-3

If above answers not working for you try this

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

Comments