Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Существует ли сложные запросы на удаление?

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Удаления поля и всех его потомков одним запросом
shum0531
Отправлено: 09 Августа, 2013 - 09:05:38
Post Id



Гость


Покинул форум
Сообщений всего: 92
Дата рег-ции: Янв. 2013  


Помог: 0 раз(а)




структура такова:
CODE (SQL):
скопировать код в буфер обмена
  1. CREATE TABLE IF NOT EXISTS `test_menu` (
  2.   `id` int(11) NOT NULL AUTO_INCREMENT,
  3.   `id_parent` int(11) DEFAULT NULL,
  4.   `name` varchar(20) NOT NULL,
  5.   PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ;


Допустим имеем поле id=2, как одним запросом удалить это поле и всех потомков (сколько ступеней дерева не известно)

на данный момент использую 2 запроса в базу для данной процедуры
1. нахожу все существующие id потомков
2. удаляю все эти id

Возможно ли составить один запрос на удаление
 
 Top
imya
Отправлено: 09 Августа, 2013 - 09:13:37
Post Id



Участник


Покинул форум
Сообщений всего: 1472
Дата рег-ции: Сент. 2012  
Откуда: Запорожье, Украина


Помог: 19 раз(а)




CODE (SQL):
скопировать код в буфер обмена
  1. DELETE FROM test_menu WHERE id = 2 AND parent_id = 2
?


-----
PHP:
скопировать код в буфер обмена
  1. do {box != cat;} while (cat != box);


Когда нормальный человек, уезжая из дома одевает на жену пояс верности, веб-дизайнер ставит на нее счетчик...
 
My status
 Top
shum0531
Отправлено: 09 Августа, 2013 - 09:16:18
Post Id



Гость


Покинул форум
Сообщений всего: 92
Дата рег-ции: Янв. 2013  


Помог: 0 раз(а)




imya пишет:
CODE (SQL):
скопировать код в буфер обмена
  1. DELETE FROM test_menu WHERE id = 2 AND parent_id = 2
?


Этот запрос удаляет только одну ступень потомков, а ведь у потомков могут быть еще потомки и у них еще потомки и т.д.
 
 Top
imya
Отправлено: 09 Августа, 2013 - 09:46:10
Post Id



Участник


Покинул форум
Сообщений всего: 1472
Дата рег-ции: Сент. 2012  
Откуда: Запорожье, Украина


Помог: 19 раз(а)




Рекурсия?

Либо http://technet.microsoft.com/ru-ru/library/ms180199.aspx

(Отредактировано автором: 09 Августа, 2013 - 09:47:10)



-----
PHP:
скопировать код в буфер обмена
  1. do {box != cat;} while (cat != box);


Когда нормальный человек, уезжая из дома одевает на жену пояс верности, веб-дизайнер ставит на нее счетчик...
 
My status
 Top
shum0531
Отправлено: 09 Августа, 2013 - 09:52:42
Post Id



Гость


Покинул форум
Сообщений всего: 92
Дата рег-ции: Янв. 2013  


Помог: 0 раз(а)




imya пишет:
Рекурсия?


А если полей окажется пару сотен? Пару сотен раз пнем базу?

В общем думаю оставить так как есть. Так как для данной ситуации есть видимо только решение в 2 запроса.
 
 Top
Мелкий Супермодератор
Отправлено: 09 Августа, 2013 - 09:52:51
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Какая СУБД?
MySQL не умеет такой фокус, а полноценные СУБД умеют делать рекурсивные запросы.


-----
PostgreSQL DBA
 
 Top
Bio man
Отправлено: 09 Августа, 2013 - 10:04:31
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2751
Дата рег-ции: Июль 2010  
Откуда: Даугавпилс, Латвия


Помог: 52 раз(а)




А триггером не получится?
(Добавление)
Мелкий пишет:
полноценные СУБД
Какие?
 
 Top
Мелкий Супермодератор
Отправлено: 09 Августа, 2013 - 10:05:56
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Триггер не может модифицировать эту же самую таблицу.


-----
PostgreSQL DBA
 
 Top
shum0531
Отправлено: 09 Августа, 2013 - 10:06:18
Post Id



Гость


Покинул форум
Сообщений всего: 92
Дата рег-ции: Янв. 2013  


Помог: 0 раз(а)




Планируется использовать пока MySQL хостеров
 
 Top
Мелкий Супермодератор
Отправлено: 09 Августа, 2013 - 10:07:43
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Bio man пишет:
Какие?

Postgresql, Oracle
DB2 и MS SQL тоже должны уметь.


-----
PostgreSQL DBA
 
 Top
Champion Супермодератор
Отправлено: 09 Августа, 2013 - 10:08:22
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




Если не mysql, то
CODE (SQL):
скопировать код в буфер обмена
  1. WITH treeIds AS
  2. SELECT id FROM tbl WHERE id = 2
  3. UNION ALL
  4. SELECT 1 FROM tbl WHERE tbl.id = treeIds.parent_id
  5. DELETE FROM tbl WHERE id IN (SELECT IF FROM treeIds)

Поподробнее - рекурсивные CTE.

Если mysql, то несолько вариантов
1. Получить айдишки во временную таблицу запросом с несколькими джойнами и юнионами и удалить по этим айдишкам:
CODE (SQL):
скопировать код в буфер обмена
  1. CREATE TEMPORARY table__tmp AS
  2. SELECT id FROM tbl WHERE id = 2
  3. UNION ALL
  4. SELECT t2.id FROM tbl t1 JOIN tbl t2 ON t2.parent_id = t1.parent_id WHERE t1.id = 2
  5. UNION ALL
  6. SELECT t3.id FROM tbl t1 JOIN tbl t2 ON t2.parent_id = t1.parent_id JOIN tbl t3 ON t3.parent_id = t2.parent_id WHERE t1.id = 2
  7. ...;
  8. DELETE FROM tbl WHERE id IN (SELECT * FROM __tmp)


2. Создать строковый столбец pathToRoot, содержащий для каждой строки путь к ней со всеми айдишками с разделителем типа 0,2,33,44
и удалить delete from tbl where pathToRoot like '0,2,%'.
pathToRoot обновлять триггером при вставке и обновлении. Правда для обновления значений pathToRoot в дочерних строках придется дополнительно вызывать что-то типа update tbl set id=id чтобы триггер всё проставил (либо делать update + replace приложением)

3. Внешний ключ с каскадным удалением (не знаю, будет ли работать, но почему бы нет)
 
 Top
shum0531
Отправлено: 09 Августа, 2013 - 10:21:58
Post Id



Гость


Покинул форум
Сообщений всего: 92
Дата рег-ции: Янв. 2013  


Помог: 0 раз(а)




CODE (SQL):
скопировать код в буфер обмена
  1. CREATE TEMPORARY table__tmp AS
  2. SELECT id FROM tbl WHERE id = 2
  3. UNION ALL
  4. SELECT t2.id FROM tbl t1 JOIN tbl t2 ON t2.parent_id = t1.parent_id WHERE t1.id = 2
  5. UNION ALL
  6. SELECT t3.id FROM tbl t1 JOIN tbl t2 ON t2.parent_id = t1.parent_id JOIN tbl t3 ON t3.parent_id = t2.parent_id WHERE t1.id = 2
  7. ...;
  8. DELETE FROM tbl WHERE id IN (SELECT * FROM __tmp)


У меня сейчас почти так же, в 2 запроса.
Вроде что хотел узнать, узнал
Спасибо всем
::closed::
 
 Top
imya
Отправлено: 09 Августа, 2013 - 10:22:10
Post Id



Участник


Покинул форум
Сообщений всего: 1472
Дата рег-ции: Сент. 2012  
Откуда: Запорожье, Украина


Помог: 19 раз(а)




Champion пишет:
Если не mysql, то
CODE (SQL):
скопировать код в буфер обмена
  1. WITH treeIds AS
  2. SELECT id FROM tbl WHERE id = 2
  3. UNION ALL
  4. SELECT 1 FROM tbl WHERE tbl.id = treeIds.parent_id
  5. DELETE FROM tbl WHERE id IN (SELECT IF FROM treeIds)

Поподробнее - рекурсивные CTE.

Если mysql, то несолько вариантов


Самый оптимальный вариант...как-то про CTE забыл Растерялся


-----
PHP:
скопировать код в буфер обмена
  1. do {box != cat;} while (cat != box);


Когда нормальный человек, уезжая из дома одевает на жену пояс верности, веб-дизайнер ставит на нее счетчик...
 
My status
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB