views:

278

answers:

4
UPDATE forms SET

pos = (SELECT MIN(pos)-1 FROM forms)

WHERE id=$id

This doesn't work, error message:

**You can't specify target table 'form' for update in FROM clause**

I hope it's clear: I want to get the minimal element-1 from the same table and assign it to pos

+2  A: 

Your problem is stated plainly in the MySQL manual:

Currently, you cannot update a table and select from the same table in a subquery.

You'll want to use a transaction. Turn AutoCommit off, begin a transaction, then do a SELECT MIN(pos)-1 FROM forms FOR UPDATE, take that result, do the update with it, then commit your transaction.

Conspicuous Compiler
+3  A: 

Consp is right that it's not supported. There's a workaround, however:

UPDATE forms SET
pos = (SELECT MIN(pos)-1 FROM (SELECT * FROM forms) AS x)
WHERE id=$id

A version that is probably faster:

UPDATE forms 
SET pos = (SELECT pos-1 FROM (SELECT MIN(pos) AS pos FROM forms) AS x)
where id=$id
Mark Byers
+1 for "screw your arbitrary whimsical restrictions". hope it works though, i don't use mysql myself anymore.
just somebody
WORKING!!! Respect MARK!!!
Dan
... guys do not forget to use isnull() in case the table is empty
Dan
I have tried to make it a little faster, but I haven't measured the performance. You may have to play around a bit to see what works best for your data.
Mark Byers
It's not an arbitrary whimsical restriction... It's because the SELECT should result in locking the relevant rows, but the rows are already being locked by the UPDATE statement, and no one's coded the logic to do proper locking without causing the statement to potentially deadlock itself. -- Note that by creating a temporary table that you're selecting into, this UPDATE statement isn't actually atomic, and multiple UPDATEs with the same pos could potentially be made.
Conspicuous Compiler
A: 

You could also try:

START TRANSACTION;
SET @newMin := MIN(pos)-1 FROM forms;
UPDATE forms SET pos=@newMin WHERE id='$id';
COMMIT;
cmptrgeekken
A: 

I think that you can not use a subquery inside an update statement, but any way there are workarounds for it ...

Here is a Quotation from the following site:

"dev.mysql.com"

“Currently, you cannot delete from a table and select from the same table in a sub-query ”

6alabati-Rashid