简体   繁体   中英

Why does SQL query not update specific row

Suppose I have this query:

UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max(customerid));

Which is meant to change the customer age to 17 for the highest customerid. But, all customer's age change to this value, regardless of ID, why is this?

The result of:

(SELECT max(customerid))

is not the maximum customerid of the table since you did not include a FROM clause.
What is odd is that the code runs without any errors and as it seems this SELECT returns the customerid of each row!!!
But even if you included the FROM clause the code would result in the error:

Error: ER_UPDATE_TABLE_USED: You can't specify target table 'customerDetails ' for update in FROM clause

Mysql allows the subquery only if it is nested inside another one like this:

UPDATE customerDetails 
SET age = 17
WHERE customerid = (SELECT t.maxid FROM (SELECT max(customerid) maxid FROM customerDetails) t);

You can do it like this:

UPDATE customerDetails 
SET age = 17
ORDER BY customerid DESC 
LIMIT 1

What this does is selecting all the data, then order's it by customerid in descending order(that means the first one will be the one with the largest customerid) and then takes the first result with LIMIT 1 and makes an update to that row.

Here is a small DEMO

One more way to do it is:

with cte as(
select max(customerid) as id 
from customerDetails
)
update  customerDetails c
set age = 17 
where c.customerid = (select id from cte);

The query doesn't make sense. You are saying WHERE customerid = (SELECT max(customerid)) This would get the max id for each row individually. If you want just the max id from the entire table, you need to check the entire table again. You can do this by doing it this way:

UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max(c.customerid) FROM customerDetails c);
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max(customerid));

What is happening here? The update statement goes through the table row by row and checks whether the row matches the select clause. In the subquery there is no from clause, so you are not selecting from some table there. Instead you access the customerid of the row you are currently looking at (it is the only customerid that exists in that context). This is one value (one row, one column) and the maximum of that value is the value itself. So, what you have is:

UPDATE customerDetails SET age = 17
WHERE customerid = customerid;

The condition customerid = customerid is true for every row in the table and you update all rows hence.

What you want instead is to update the row the customerid of which matches the maximum customerid in the table:

UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT MAX(customerid) FROM customerDetails);

MySQL, however, has problems with accessing the same table that you are updating. So you will have to select from the table one level deeper, which makes this a tad clumsy:

UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT MAX(customerid) FROM (SELECT * FROM customerDetails) q);

The following should work:

create table temp as select max(customerid) max_id from customerDetails;
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max_id from temp);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM