notatnik.net.pl

MySQL, MariaDB: jak usunąć dane z tabeli, z podzapytaniem, w którym użyta jest ta sama tabela?

Poniedziałek, 20.03.2017

Załóżmy, że w bazie MySQL, lub MariaDB, mamy tabelę, w której znajdują się ogłoszenia użytkowników. Chcemy usunąć z niej najnowsze ogłoszenie każdego użytkownika. Standardowo, próba usunięcia danych z tabeli MySql, za pomocą zapytania DELETE FROM table WHERE id IN (SELECT MAX(id) FROM table ...) skutkuje błędem. W jaki sposób możemy usunąć dane z tabeli z podzapytaniem do tej samej tabeli?

Nasza tabela w uproszczeniu będzie wyglądać tak: CREATE TABLE `offers` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`data` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
);
Dodamy do niej kilka rekordów: INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (1, 1, 1);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (2, 1, 2);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (3, 1, 3);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (4, 2, 1);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (5, 2, 2);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (6, 2, 3);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (7, 3, 1);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (8, 3, 2);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (9, 3, 3);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (10, 3, 4);
INSERT INTO `offers` (`id`, `user_id`, `data`) VALUES (11, 3, 5);
Teraz z naszej tabeli chcemy, każdemu użytkownikowi, usunąć ostatnio dodaną ofertę. W tym przypadku będą to oferty o id: 3, 6, 11. Napiszemy zapytanie usuwające dane: DELETE FROM offers WHERE id IN (SELECT MAX(id) FROM offers GROUP BY user_id) Jednak takie zapytanie zwróci błąd:
- dla bazy MySQL
Error Code: 1093. You can't specify target table `offers` for update in FROM clause -dla bazy MariaDB Error Code: 1093. Table `offers` is specified twice, both as a target for DELETE and as a separate source for data Rozwiązaniem tego problemu będzie zapytanie: DELETE FROM offers WHERE id IN (SELECT * FROM (SELECT MAX(id) FROM offers GROUP BY user_id) o) Pozwoli nam ono prawidłowo usunąć odpowiednie rekordy z tabeli.

Zobacz też:

PHP, MySQL: Wymuszenie kodowania znaków z bazy danych