You can't update a table you're selecting from
I needed to calculate the font size daily for displaying genres on Kinsburg. And I ran into a problem: you can’t select data from a table that’s being updated.
Here are some example queries
Let’s try the straightforward approach:
update `categories` set `size` = (`count` / ((max(`count`) - min(`count`)) / 10));
ERROR 1111 (HY000): Invalid use of group function
Let’s try a nested SELECT:
update `categories` set `size` = (select (`count` / ((max(`count`) - min(`count`)) / 10)) from `categories`);
ERROR 1093 (HY000): You can't specify target table 'categories' for update in FROM clause
Let’s try a JOIN:
update `categories` as `c1`
JOIN `categories` as `c2`
using(`category_id`)
set `c1`.`size` = (`c2`.`count` / ((max(`c2`.`count`) - min(`c2`.`count`)) / 10));
ERROR 1111 (HY000): Invalid use of group function
Everything works separately
Get the “font size”:
select (`count` / ((max(`count`) - min(`count`)) / 10)) from `categories`;
+--------------------------------------------------------+
| (`count` / ((max(`count`) - min(`count`)) / 10)) |
+--------------------------------------------------------+
| 3.47826087 |
+--------------------------------------------------------+
1 row in set (0.00 sec)
Update the font size field:
update `categories` set `size` = 3.47826087;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 21 Changed: 0 Warnings: 0
Solution
After some googling and racking my brains with disc, I arrived at the solution below.
I decided to put the percentage calculation into the @percent variable, then created a view for the “categories” table and joined the table to the view:
-- создаем коэффициент деления
set @percent = (select (max(`count`) - min(`count`)) / 10 from `categories`);
-- создаем вьюху
create view `categories_view` as select `category_id`, `count` from `categories`;
-- жойним таблицу и вьюху, обновляя данные
update `categories` as `c`
join `categories_view` as `cv`
using(`category_id`)
set `c`.`size` = `cv`.`count` / @percent;
That’s all—happy manual-reading :)
UPDATE: Let’s create a procedure and an event for this task
/* Создаем вьюху и процедуру для установки размеров шрифта */
use kinsburg;
/* создаем вьюху */
CREATE VIEW `categories_view` AS SELECT `category_id`, `count` FROM `categories`;
/* создаем процедуру */
delimiter //
DROP PROCEDURE IF EXISTS `updateCategorySize`//
CREATE PROCEDURE `updateCategorySize` ()
BEGIN
/* создаем коэффициент деления */
SET @percent = (SELECT (max(`count`) - min(`count`)) / 10 FROM `categories`);
/* жойним таблицу и вьюху, обновляя данные */
UPDATE `categories` AS `c` JOIN `categories_view` AS `cv` USING(`category_id`) SET `c`.`size` = `cv`.`count` / @percent;
END//
delimiter ;
/* создаем евент для вызова процедуры раз в сутки */
CREATE
DEFINER = kinsburg@localhost
EVENT `updateCategorySizeEvent`
ON SCHEDULE
EVERY 1 DAY
DO
CALL updateCategorySize;
Comments are closed. Read the original discussion in Russian →
