MySQL update with a subquery - mysql

I am trying to update a specific row in a table based on another value in that table, but I can't seem to figure out how to do it:
UPDATE users AS a SET a.val = (SELECT value FROM users WHERE userid = 4) WHERE a.userID = 1
but I am getting the error
Lookup Error - MySQL Database Error: You can't specify target table 'a' for update in FROM clause
Any ideas what I am missing here?

Use JOIN syntax and a non-equi join
UPDATE users a JOIN users b
ON a.userID = 1
AND b.userid = 4
SET a.value = b.value
Here is SQLFiddle demo

Related

SQL Update list of records coming from select

I need to update a list of records coming from a SELECT statement I'm trying with something of this kind but I got errors regarding the statement format:
UPDATE
noleggio_veicoli
SET
data_esportazione = CURDATE()
WHERE id IN
(SELECT id FROM noleggio_veicoli WHERE id_convenzionato = 3);
But it just returns:
Error Code: 1093. You can't specify target table 'noleggio_veicoli'
for update in FROM clause
It looks like MySQL is only able to run classic UPDATE i.e.:
UPDATE
noleggio_veicoli
SET
data_esportazione = CURDATE()
WHERE
id_convenzionato = 3;
Unlucky this's not what I need since SELECT query I need to chain to the UPDATE statement is more complex and depends on Views already defined in the SQL server.
Like #Maxim said, you should do something like
CREATE TEMPORARY TABLE IF NOT EXISTS temp AS (
SELECT id FROM noleggio_veicoli where id_convenzionato=3
);
update noleggio_veicoli set data_esportazione=curdate()
where id in (select id from temp);
If you want to update data that match a select p.id from parent p inner join child c on c.pid=p.id left join child2 c2 on c.x=c2.y where c.xx=yy and p.x=y... you can do something like:
update parent p
set aaa=bbbb
from child c
left join child2 c2 on c.x=c2.y
where c.pid=p.id and c.xx=yy and p.x=y ...
You can specify this with a join:
UPDATE noleggio_veicoli nv JOIN
noleggio_veicoli nv3
ON nv.id = nv3.id and nvid3.id_convenzionato = 3
SET data_esportazione = curdate();
For some odd reason MySql doesn't allow to reference the same table you update in a first level subquery.
But you can work around that via a subqueryinception. (It's not a real word, probably)
I.e. using a sub-query in the sub-query.
Example using an IN:
UPDATE noleggio_veicoli
SET data_esportazione = current_date
WHERE id IN (select id from (select id from noleggio_veicoli where id_convenzionato = 3) q);
It works also with an EXISTS:
UPDATE noleggio_veicoli as t
SET data_esportazione = current_date
WHERE EXISTS
(
select 1
from (select id, id_convenzionato from noleggio_veicoli) as t2
where t2.id_convenzionato = 2
and t2.id = t.id
);
You can test it here on rextester
You can't update and read from one table at the same time. At first you must
select necessary ids and save them to somewhere, for example to temporary table

updating a column in table 1 by joining information from table 2

I have tabel 1 that has VIN which i want to update.
table 1 and table 2 has OBJ ID and POID (respectively) which are same.
I only know device ID which is present in table 2.
update table.1 set VIN = '5TDKK3DC6BS018229'
from table 2, table 1
where 2.device ID = 'TCAXLcKkt3'
and 2.OBJ = 1.POID;
I am getting SQL command not properly ended.
Make sure you remove the semi-colon at end of the query since some databases will complain if its there in TOAD.
If you are using SQL Server then following query will work.
UPDATE table1
SET VIN = '5TDKK3DC6BS018229'
FROM table1
INNER JOIN table2 ON table1.POID = table2.OBJ
WHERE table2.deviceID = 'TCAXLcKkt3'
If you want the same query for MySQL, then use the one below.
UPDATE table1 a
JOIN table2 b
ON a.poid = b.obj
SET a.vin = '5TDKK3DC6BS018229'
WHERE b.deviceid = 'TCAXLcKkt3'
If you are using Oracle, then use the query as below.
UPDATE table1
SET table1.vin = '5TDKK3DC6BS018229'
where exists (SELECT table2.obj
FROM table2
WHERE table2.obj = table1.poid
AND table2.deviceid = 'TCAXLcKkt3')
Error message looks like you are using Oracle.
If am not wrong this is what you are looking for
UPDATE table1
SET vin = '5TDKK3DC6BS018229'
WHERE EXISTS (SELECT 1
FROM table2 B
WHERE table1.obj = B.poid
AND B."device id" = 'TCAXLcKkt3')
In Oracle to update table from another table using Join try the below syntax
UPDATE
(SELECT A.VIN
FROM table1 A
INNER JOIN table2 B
ON A.OBJ = B.POID
WHERE B."device ID" = 'TCAXLcKkt3'
) t
SET T.VIN = '5TDKK3DC6BS018229'

Incorrect usage of UPDATE and LIMIT

When I execute the following query:
UPDATE `table1`
INNER JOIN Address ON Address.Mobile = table1.number
LEFT JOIN tps ON tps.number = table1.number
SET table1.export = '2015-03-31'
WHERE Address.Surname != '' and tps.number is null AND table1.export = '0000-00-00'
limit 100000
I get error:
Incorrect usage of UPDATE and LIMIT
I need to use Limit when using Update join. How to solve this issue?
Think it is objecting to the use of order / limit on a multi table update statement.
I would suggest trying to to do an update where the key field is in the results of a sub query that returns the limited set of records. One problem here is that MySQL will not allow you to update a table that is also in the sub query, but you can normally get around this by having a 2nd containing sub query.
Something like this:-
UPDATE table1
SET table1.export = '2015-03-31'
WHERE table1.number IN
(
SELECT number
FROM
(
SELECT table1.number
FROM `table1`
INNER JOIN Address ON Address.Mobile = table1.number
LEFT JOIN tps ON tps.number = table1.number
WHERE Address.Surname != '' and tps.number is null AND table1.export = '0000-00-00'
limit 100000
) sub1
) sub2

Delete, Update with derived tables?

I have just studied FROM clause and derived tables in mysql and most of the websites provided the examples using SELECT command
Example SELECT * FROM (SELECT * FROM usrs) as u WHERE u.name = 'john'
But when I have tried using delete or update command it does not seem to work.
Example DELETE FROM (SELECT * FROM usrs) as u WHERE u.name = 'john'
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near (SELECT * FROM usrs) as u WHERE u.name = 'john' at line
UPDATE (SELECT * FROM usrs) as u SET u.lname ='smith' WHERE u.name = 'john'
1288 The target table e of the UPDATE is not updatable
So derived tables does not work with delete or update commands? or is there a way to make it work.
Instead of writing the table name for update and delete I want to write a subquery that gets the records and perform the delete operation on that records? Is that possible in mysql?
UPDATED I have to delete a record and i have three tables, the record may exist in any of the table
My approach delete from first table rows effected? quit: else check second table rows effected? quit : else check third table
But if I use UNION ALL I can do this way
Delete from (select * from tb1 union all select * from tb2 union all select * from tb3) e as e.uname = 'john'
but this query does not seem to work , now could anyone tell me how do i delete or update a record when i have more than one table to search. Any help is greatly appreciated.
You can't directly delete from the subquery, but you can still use it if you'd like, you'll just need to use it in a JOIN:
DELETE usrs
FROM usrs
INNER JOIN (
SELECT * FROM usrs WHERE name = 'john'
) t ON usrs.Id = t.Id
Or you could use IN:
DELETE usrs
WHERE ID IN (
SELECT ID
FROM usrs
WHERE name = 'John'
)
With this said, for this example, I don't know why you'd want a subquery:
DELETE usrs WHERE name = 'John'
Edit base on comments. To delete from multiple tables at the same time, you can either have multiple DELETE statements, or you can use something like the following:
delete t1, t2, t3
from (select 'john' as usr) t
left join t1 on t.usr=t1.usr
left join t2 on t.usr=t2.usr
left join t3 on t.usr=t3.usr
SQL Fiddle Demo
Derived tables exist only for the duration of the parent query they're a member of. Assuming that this syntax and the operations were allowed by MySQL, consider what happens:
a) Your main query starts executing
b) the sub-query executes and returns its results as a temporary table
c) the parent update changes that temporary table
d) the parent query finishes
e) temporary tables are cleaned up and deleted
Essentially you'll have done nothing except waste a bunch of cpu cycles and disk bandwidth.
UPDATE queries DO allow you to join against other tables to use in the WHERE clause, e.g..
UPDATE maintable
LEFT JOIN othertable ON maintable.pk = othertable.fk
SET maintable.somefield='foo'
WHERE othertable.otherfield = 'bar'

Can't delete all records except first one

I'm trying to delete all records from a certain user except the first one, however I'm getting this error:
1093 - You can't specify target table 'History' for update in FROM clause
I don't understand what's the problem and also I found a similar question in SO that proposed this same solution. This is my query:
DELETE FROM `History` WHERE ID = '3' AND Date NOT IN (SELECT min(Date) FROM `History` WHERE ID = '3')
Try converting it to JOIN
DELETE a
FROM History a
LEFT JOIN History b
ON a.Date = b.Date AND
b.ID = 3
WHERE b.date IS NULL AND
a.ID = 3
Before executing the statement above, please do backup the table first.
Here is another way to solve this problem, by wrapping the subquery in another layer of a subquery. MySQL generates the intermediate query, which prevents this error:
DELETE FROM `History`
WHERE ID = '3' AND
Date NOT IN (select mindate
from (SELECT min(Date) as mindate FROM `History` WHERE ID = '3')
)
Please try the below query once
DELETE FROM `History` main WHERE main.ID = '3'
AND main.Date NOT IN
(SELECT min(inn.Date) FROM `History` WHERE main.ID = inn.id)