Bug #46534 Allow reference to same table in UPDATE subquery
Submitted: 3 Aug 2009 20:31 Modified: 4 Aug 2009 17:45
Reporter: Chris Hennick Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: DML Severity:S3 (Non-critical)
Version: OS:Any
Assigned to: CPU Architecture:Any

[3 Aug 2009 20:31] Chris Hennick
Description:
Some UPDATES would be more convenient if the table being updated could be used in a subquery. MySQL could accomplish this by creating a temporary copy of the table and using the copy for the subquery. For instance, today I had a table part of which was the following:

mysql> select name, released, block, rotation_block from cardset where rotation_block is not null or block = '(core)' order by released;                                                                                            
+-------------------------+------------+-------------+----------------+                                           
| name                    | released   | block       | rotation_block |                                           
+-------------------------+------------+-------------+----------------+                                           
| Limited Edition Alpha   | 1993-08-05 | (core)      | NULL           |                                           
| Limited Edition Beta    | 1993-10-01 | (core)      | NULL           |                                           
| Unlimited Edition       | 1993-12-01 | (core)      | NULL           |                                           
| Revised Edition         | 1994-04-01 | (core)      | NULL           |                                           
| Fourth Edition          | 1995-04-01 | (core)      | NULL           |                                           
| Ice Age                 | 1995-06-01 | Ice Age     | Ice Age        |                                           
| Alliances               | 1996-06-10 | Ice Age     | Ice Age        |                                           
| Mirage                  | 1996-10-08 | Mirage      | Mirage         |                                           
| Visions                 | 1997-02-03 | Mirage      | Mirage         |                                           
| Fifth Edition           | 1997-03-24 | (core)      | NULL           |                                           
| Weatherlight            | 1997-06-09 | Mirage      | Mirage         |                                           
| Tempest                 | 1997-10-14 | Tempest     | Tempest        |                                           
| Stronghold              | 1998-03-02 | Tempest     | Tempest        |                                           
| Exodus                  | 1998-06-15 | Tempest     | Tempest        |                                           
| Urza's Saga             | 1998-10-12 | Urza        | Urza           |                                           
| Urza's Legacy           | 1999-02-15 | Urza        | Urza           |                                           
| Classic Sixth Edition   | 1999-04-28 | (core)      | NULL           |                                           
| Urza's Destiny          | 1999-06-07 | Urza        | Urza           |                                           
| Mercadian Masques       | 1999-10-04 | Masques     | Masques        |                                           
| Nemesis                 | 2000-02-14 | Masques     | Masques        |                                           
| Prophecy                | 2000-06-05 | Masques     | Masques        |                                           
| Invasion                | 2000-10-02 | Invasion    | Invasion       |                                           
| Planeshift              | 2001-02-05 | Invasion    | Invasion       |                                           
| Seventh Edition         | 2001-04-11 | (core)      | NULL           |                                           
| Apocalypse              | 2001-06-04 | Invasion    | Invasion       |                                           
| Odyssey                 | 2001-10-01 | Odyssey     | Odyssey        |                                           
| Torment                 | 2002-02-04 | Odyssey     | Odyssey        |                                           
| Judgment                | 2002-05-27 | Odyssey     | Odyssey        |                                           
| Onslaught               | 2002-10-07 | Onslaught   | Onslaught      |                                           
| Legions                 | 2003-02-03 | Onslaught   | Onslaught      |                                           
| Scourge                 | 2003-05-26 | Onslaught   | Onslaught      |                                           
| Eighth Edition          | 2003-07-28 | (core)      | NULL           |                                           
| Mirrodin                | 2003-10-02 | Mirrodin    | Mirrodin       |                                           
| Darksteel               | 2004-02-06 | Mirrodin    | Mirrodin       |                                           
| Fifth Dawn              | 2004-06-04 | Mirrodin    | Mirrodin       |                                           
| Champions of Kamigawa   | 2004-10-01 | Kamigawa    | Kamigawa       |                                           
| Betrayers of Kamigawa   | 2005-02-04 | Kamigawa    | Kamigawa       |                                           
| Saviors of Kamigawa     | 2005-06-03 | Kamigawa    | Kamigawa       |                                           
| Ninth Edition           | 2005-07-29 | (core)      | NULL           |                                           
| Ravnica: City of Guilds | 2005-10-07 | Ravnica     | Ravnica        |                                           
| Guildpact               | 2006-02-03 | Ravnica     | Ravnica        |                                           
| Dissension              | 2006-05-05 | Ravnica     | Ravnica        |                                           
| Coldsnap                | 2006-07-21 | Ice Age     | Time Spiral    |                                           
| Time Spiral             | 2006-10-06 | Time Spiral | Time Spiral    |                                           
| Planar Chaos            | 2007-02-02 | Time Spiral | Time Spiral    |                                           
| Future Sight            | 2007-05-04 | Time Spiral | Time Spiral    |                                           
| Tenth Edition           | 2007-07-14 | (core)      | NULL           |                                           
| Lorwyn                  | 2007-10-12 | Lorwyn      | Lorwyn         |                                           
| Morningtide             | 2008-02-01 | Lorwyn      | Lorwyn         |                                           
| Shadowmoor              | 2008-05-02 | Shadowmoor  | Lorwyn         |                                           
| Eventide                | 2008-07-25 | Shadowmoor  | Lorwyn         |                                           
| Shards of Alara         | 2008-10-03 | Alara       | Alara          |                                           
| Conflux                 | 2009-02-06 | Alara       | Alara          |                                           
| Alara Reborn            | 2009-04-30 | Alara       | Alara          |                                           
| Magic 2010              | 2009-07-17 | (core)      | Alara          |                                           
| Zendikar                | 2009-10-02 | Zendikar    | Zendikar       |                                           
+-------------------------+------------+-------------+----------------+ 

I wanted to change each NULL in rotation_block to the value above it if there was one.

How to repeat:
mysql> update cardset set rotation_block = (select rotation_block from cardset other where other.released <= cardset.released and rotation_block is not null order by other.released desc limit 1) where block = '(core)';

ERROR 1093 (HY000): You can't specify target table 'cardset' for update in FROM clause        

Suggested fix:
MySQL could treat this as equivalent to the following, which is what I ended up doing:

create temporary table cardset2 like cardset;
insert into cardset2 select * from cardset;
update cardset set rotation_block = (select rotation_block from cardset2 where cardset2.released <= cardset.released and rotation_block is not null order by cardset2.released desc limit 1) where block = '(core)';
drop table cardset2;
[4 Aug 2009 3:52] Valeriy Kravchuk
Thank you for the feature request.
[4 Aug 2009 17:45] Valeriy Kravchuk
Actually, this is a duplicate of Bug #23353.