1698

I need to update this table in SQL Server with data from its 'parent' table, see below:

Table: sale

id (int) udid (int) assid (int) 

Table: ud

id (int) assid (int) 

sale.assid contains the correct value to update ud.assid.

What query will do this? I'm thinking of a join but I'm not sure if it's possible.

5
  • 1
    some relations between the tables? How can one know which record from sale corresponds to which record from ud? Is it based on id as primary key in both tables? Commented Aug 18, 2009 at 11:43
  • How can you update UD? It only has the assid and it's own ID. Could you give an example in terms of actual values that exist, and the records you would like changed or added as a result of the script? Commented Aug 18, 2009 at 11:43
  • 4
    See also SO question ... stackoverflow.com/questions/982919/sql-update-query-using-joins Commented Jun 14, 2013 at 14:48
  • 2
    User Alias in query like stackoverflow.com/questions/982919/sql-update-query-using-joins Commented Aug 15, 2017 at 11:46
  • UPDATE s SET s.Age = s.Age + 1 FROM Students s INNER JOIN StudentsData sd ON s.ID = sd.ID; Commented Nov 9 at 22:20

18 Answers 18

2994

Syntax strictly depends on which SQL DBMS you're using. Here are some ways to do it in ANSI/ISO (aka should work on any SQL DBMS), MySQL, SQL Server, and Oracle. Be advised that my suggested ANSI/ISO method will typically be much slower than the other two methods, but if you're using a SQL DBMS other than MySQL, SQL Server, or Oracle, then it may be the only way to go (e.g. if your SQL DBMS doesn't support MERGE):

ANSI/ISO:

update ud set assid = ( select sale.assid from sale where sale.udid = ud.id ) where exists ( select * from sale where sale.udid = ud.id ); 

MySQL:

update ud u inner join sale s on u.id = s.udid set u.assid = s.assid 

SQL Server:

update u set u.assid = s.assid from ud u inner join sale s on u.id = s.udid 

PostgreSQL:

update ud set assid = s.assid from sale s where ud.id = s.udid; 

Note that the target table must not be repeated in the FROM clause for Postgres. Main question: How to do an update + join in PostgreSQL?

Oracle:

update (select u.assid as new_assid, s.assid as old_assid from ud u inner join sale s on u.id = s.udid) up set up.new_assid = up.old_assid 

SQLite:

update ud set assid = ( select sale.assid from sale where sale.udid = ud.id ) where RowID in ( select RowID from ud where sale.udid = ud.id ); 

SQLite 3.33 added support for an UPDATE + FROM syntax analogous to the PostgreSQL one:

update ud set assid = s.assid from sale s where ud.id = s.udid; 

Main question: Update with Join in SQLite

Sign up to request clarification or add additional context in comments.

4 Comments

I am never sure on this, but is it better practice to use CAPITALIZED SQL keywords or lowercase (like here)? (Or does it not matter)
@Password-Classified it used to matter a long time ago when people didnt have syntax highlighting; now its fine to write sql all lower case and it looks much better imo
please don't use "ass ID" as a field name
The note about NOT repeating the target table in Postgres is priceless! Thx, @a_horse_with_no_name
178

This should work in SQL Server:

update ud set assid = sale.assid from sale where sale.udid = id 

Comments

134

PostgreSQL

UPDATE table1 SET COLUMN = value FROM table2, table3 WHERE table1.column_id = table2.id AND table1.column_id = table3.id AND table1.COLUMN = value AND table2.COLUMN = value AND table3.COLUMN = value 

3 Comments

The answer would be more handy if it would use the table/column names used in the question. Why are there 3 tables in your answer?
The OP has left the building: "Last seen more than 5 years ago"
@PeterMortensen LOL
67

A standard SQL approach would be

UPDATE ud SET assid = (SELECT assid FROM sale s WHERE ud.id=s.id) 

On SQL Server you can use a join

UPDATE ud SET assid = s.assid FROM ud u JOIN sale s ON u.id=s.id 

Comments

48

PostgreSQL:

CREATE TABLE ud (id integer, assid integer); CREATE TABLE sales (id integer, udid integer, assid integer); UPDATE ud SET assid = sales.assid FROM sales WHERE sales.id = ud.id; 

Comments

34

Simplified update query using JOIN-ing multiple tables.

 UPDATE first_table ft JOIN second_table st ON st.some_id = ft.some_id JOIN third_table tt ON tt.some_id = st.some_id ..... SET ft.some_column = some_value WHERE ft.some_column = 123456 AND st.some_column = 123456 

Note - first_table, second_table, third_table and some_column like 123456 are demo table names, column names and ids. Replace them with the valid names.

Comments

20

Another example why SQL isn't really portable.

For MySQL it would be:

update ud, sale set ud.assid = sale.assid where sale.udid = ud.id; 

For more info read multiple table update: http://dev.mysql.com/doc/refman/5.0/en/update.html

UPDATE [LOW_PRIORITY] [IGNORE] table_references SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ... [WHERE where_condition] 

Comments

17

Teradata's Aster offers another interesting way how to achieve the goal:

MERGE INTO ud --what table should be updated USING sale -- from what table/relation update info should be taken ON ud.id = sale.udid --join condition WHEN MATCHED THEN UPDATE SET ud.assid = sale.assid; -- how to update 

1 Comment

interesting in a way that is a bit different what other tools provide (at least in the time I wrote the answer :))
16

I was thinking the SQL Server one in the top post would work for Sybase since they are both T-SQL, but unfortunately not.

For Sybase, I found the update needs to be on the table itself, not the alias:

update ud set u.assid = s.assid from ud u inner join sale s on u.id = s.udid 

Comments

14

The simplest way is to use the Common Table Expression (CTE) introduced in SQL Server 2005:

with cte as (select u.assid col1 ,s.assid col2 from ud u inner join sale s on u.id = s.udid) update cte set col1=col2 

Comments

13

MySQL

You'll get the best performance if you forget the where clause and place all conditions in the ON expression.

I think this is because the query first has to join the tables and then runs the where clause on that, so if you can reduce what is required to join then that's the fasted way to get the results/do the update.

Example

Scenario

You have a table of users. They can log in using their username or email or phone_number. These accounts can be active (1) or inactive (0). This table has 50000 rows

You then have a table of users to disable (blacklist) at one go because you find out they've all done something bad.

A script runs that checks for users in the blacklist_users table and disables them in the users table.

This blacklist_users table however, only has one column with usernames, emails and account numbers all mixed together.

The blacklist_users table also has a "has_run" indicator which needs to be set to 1 (true) when it has been run so it can be skipped in future queries.

So if you have a WHERE clause here, internally, the results are getting brought back in the join and then the WHERE clause is being queried against that dataset. Instead, we can move all the where clause conditions into the join, and internally, remove the second query completely.

Therefore, this is the most optimal query to avoid needless lookups of the users table...

Query

UPDATE users User INNER JOIN blacklist_users BlacklistUser ON ( User.username = BlacklistUser.account_ref OR User.email = BlacklistedUser.account_ref OR User.phone_number = BlacklistUser.account_ref AND User.is_active = 1 AND BlacklistUser.has_run = 0 ) SET User.is_active = 0, BlacklistUser.has_run = 1; 

Reasoning

If we had to join on just the OR conditions it would essentially need to check each row 4 times (1 for email, 1 for phone_number, 1 for username, 1 for is_active) to see if it should join, and potentially return a lot more rows. However, by giving it more conditions it can "skip" every row we're not updating.

Bonus

It's more readable. All the conditions are in one place and the rows to update are in another place.

I hope all that makes sense.

Comments

13

The following statement with the FROM keyword is used to update multiple rows with a join:

UPDATE users set users.DivisionId=divisions.DivisionId from divisions join users on divisions.Name=users.Division 

Comments

10

And in Microsoft Access:

UPDATE ud INNER JOIN sale ON ud.id = sale.udid SET ud.assid = sale.assid; 

Comments

9

Try this one. I think this will work for you.

update ud set ud.assid = sale.assid from ud Inner join sale on ud.id = sale.udid where sale.udid is not null 

Comments

4
UPDATE tblAppraisalBasicData SET tblAppraisalBasicData.ISCbo=1 FROM tblAppraisalBasicData SI INNER JOIN aaa_test RAN ON SI.EmpID = RAN.ID 

Comments

4

For SQLite use the RowID property to make the update:

update Table set column = 'NewValue' where RowID = (select t1.RowID from Table t1 join Table2 t2 on t1.JoinField = t2.JoinField where t2.SelectValue = 'FooMyBarPlease'); 

Comments

3

For PrestaShop users who use MySQL 5.7:

UPDATE ps_stock_available sa INNER JOIN ps_shop s ON sa.id_shop = s.id_shop AND s.id_shop = 1 INNER JOIN ps_order_detail od ON sa.id_product = od.product_id AND od.id_order = 22417 SET sa.physical_quantity = sa.quantity + sa.reserved_quantity 

This was an example, but the point is as Eric said in How can I do an UPDATE statement with JOIN in SQL Server?.

You need to add an UPDATE statement at first with the full address of all tables to join with, and then add the SET statement.

Comments

2

I had a similar situation where I needed to pick up and update user_id in orders from corporate_subscriptions in postgresql. The following query worked in my case:

update orders set user_id=cs_user_id from (select o.id, o.user_id as order_user_id, cs.id as cs_id, cs.user_id as cs_user_id from orders o right join corporate_subscriptions cs on cs.id=o.corporate_subscription_id where corporate_subscription_id is not null) o where orders.id=o.id and orders.source='Subscription'; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.