Mysql – Convert Oracle query to MySQL

MySQLoracle

I've just tried to convert this update command, which is Oracle sql, to MySQL with SQLWays and it failed with the following error:

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

source command (Oracle):

UPDATE animal_table
     SET (animal_info1, 
          animal_info2, 
          animal_info3) = (SELECT animal_nbr, animal_amount, '00'
                           FROM animal_table t2
                           WHERE t2.category_id = animal_table.category_id
                             AND t2.sumary_id = animal_table.summary_id
                             AND t2.animal_type = 'special'
                          )
  WHERE animal_type = 'cats'
    AND category_id = 'foo';

suggested target command (MySQL):

UPDATE animal_table
SET 
    animal_info1 = (SELECT animal_nbr FROM animal_table t2 
                    WHERE t2.category_id = animal_table.category_id
                    AND t2.sumary_id = animal_table.summary_id
                    AND t2.animal_type = 'special'),
    animal_info2 = (SELECT animal_amount FROM animal_table t2 
                    WHERE t2.category_id = animal_table.category_id
                    AND t2.sumary_id = animal_table.summary_id
                    AND t2.animal_type = 'special'),
    animal_info3 = (SELECT '00' FROM animal_table t2 
                    WHERE t2.category_id = animal_table.category_id
                    AND t2.sumary_id = animal_table.summary_id
                    AND t2.animal_type = 'special')
    WHERE animal_type = 'cats'
    AND category_id = 'foo';

can anyone help me out here?

Best Answer

Try using an UPDATE JOIN of the table against itself

UPDATE
    animal_table A
INNER JOIN
(
    SELECT
        category_id,summary_id,
        animal_nbr,animal_amount,'00' info3
    FROM animal_table
    WHERE animal_type = 'special'
) B USING (category_id,summary_id)
SET
    A.animal_info1 = B.animal_nbr,
    A.animal_info2 = B.animal_amount,
    A.animal_info3 = B.info3
WHERE
    A.animal_type = 'cats' AND
    A.category_id = 'foo';

Make sure that animal_table has a compound index on category_id and summary_id. If you do not have such an index, please run this:

ALTER TABLE animal_table ADD INDEX (category_id,summary_id);

UPDATE 2011-09-27 13:10 EDT

I just noticed that categrory_id 'foo' limits the dataset. Here is an updated refactoring of my answer ( I moved category_id = foo into the subquery )

UPDATE
    animal_table A
INNER JOIN
(
    SELECT
        category_id,summary_id,
        animal_nbr,animal_amount,'00' info3
    FROM animal_table
    WHERE animal_type = 'special'
    AND category_id = 'foo'
) B USING (category_id,summary_id)
SET
    A.animal_info1 = B.animal_nbr,
    A.animal_info2 = B.animal_amount,
    A.animal_info3 = B.info3
WHERE
    A.animal_type = 'cats';

I also recommend adding this additional index to accommodate the subquery

ALTER TABLE animal_table ADD INDEX (animal_type,category_id);