powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP + MySQL: удалить с учетом иерархии...
20 сообщений из 20, страница 1 из 1
PHP + MySQL: удалить с учетом иерархии...
    #33513889
Тупой!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброе время суток, All!
Помогите пожалуйста! Голова трещит, уже либо туплю окончательно, либо одно из двух...
Есть в базе таблица - каталог с неограниченным (теоретически) возможным количеством подкаталогов... Организована примерно следующим образом (все лишнее для понимания удалено):

id name level
1 <имя1> 0
2 <имя2> 0
6 <имя3> 0
7 <имя4> 1
8 <имя5> 1
13 <имя6> 8
12 <имя7> 8


ID - поле auto_increment просто счетчик, идентификатор каждого подкаталога...
name - все понятно, просто название каталога/подкаталога...
и level - это уровень иерархии (то есть где level = '0' - это корневой каталог, где level = '1' - это подкаталог, внутри каталога имеющего ID = 1)

Вот так сумбурно написал, но смысл ясен, думаю... В моем примере каталог с именем "имя1" содержит 2 подкаталога: "имя4" и "имя5"... и в свою очередь подкаталог "имя5" содержит еще 2 подкаталога: "имя6" и "имя7"...

Я удаляю главный каталог "имя1" и мне необходимо, чтобы все, что внутри тоже удалялось... Проблема в том, что глубина вложения не ограничена и может быть очень немалой!

Каким образом на PHP мне лучше организовать удаление?
Предлагайте алгоритмы/готовые куски кода - приветствуется ВСЁ!
С базами работаю очень недавно, поэтому если что-то не так - прошу сильно не пинать! :)

Заранее спасибо.
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33513920
Фотография Duke1999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неплохой ник :)
а причем здесь php?
это запрос к SQL серверу "УДАЛИТЬ ИЗ имя_таблицы ГДЕ level = 1"
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33514171
Тупой!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Duke1999, спасибо! :)

Так понятное дело, что запрос к MySQL, но запрос-то я формирую из PHP скрипта...

Так то ясно, что в моем случае сначала я должен получить в массив все IDшники через запрос (1) "SELECT * FROM table WHERE level=$id"($id - передаю потому что через переменную в PHP, это самый старший для удаления уровень)...

Далее удалить старший уровень:
(2) "DELETE FROM table WHERE id=$id" ...

Затем аналогично пробегаться по всем элементам массива с полученными ID в результате первого запроса и т.д... Но еще раз повторюсь - вложений может быть до черта великого! :( Нужен некий цикл максимально оптимизированный... Я не могу больше уследить за всеми вложениями - поплыли мозги совершенно...
Потому и прошу помощи!!!
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33514398
Фотография Robert Tappan Moris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Удалять из таблицы можно указывая список значений:
Код: plaintext
1.
DELETE FROM <Таблица> WHERE <поле> IN (<Список значений через запятую>)

Таким образом нужно рекурсивно пройти по удаляемым подкаталогам и составить этот самый список:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
// рекурсивный проход по текущему каталогу
function GoOn($CurId,$List,$Field,$TblName) {
	$List.=",".$CurId;
	$sql = "SELECT `$Field` FROM `$TblName` WHERE `level`=$CurId";
	$rst = mysql_query($sql);
	while ($row=mysql_fetch_row($rst)) {
    	$List=GoOn($row[ 0 ],$List);
	}
	return $List;
}

// запуск удаления
function RekurDel($DelId,$Field,$TblName) {
	// соединение
	$DelId =  1 ;
	$List ="";
	$List = GoOn($DelId,$List,$Field,$TblName);
	$List = substr($List, 1 );
	$sql = "DELETE FROM `$TblName` WHERE `$Field` IN ($List)";
	mysql_query($sql);
	// отключение
}

Теперь осталось прикрутить подключение и отключение и вызывать RekurDel(<id удаляемого каталого>,<Ключевое поле>,<Название таблицы>).

--------------------
Чтобы понять рекурсию, нужно понять рекурсию. (с)
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33514405
Фотография Robert Tappan Moris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только строчку
Код: plaintext
1.
$DelId =  1 ;
нужно удалить =)
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33515493
Тупой!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВСЕ ОТЛИЧНО! Все супер! ЭТО ТО, что мне нужно было... ОГРОМНОЕ спасибо...

Единственное - не хочет у меня MySQL выполнять
$query = "DELETE FROM table WHERE `id` IN ($list)";
хотя в $list -все как нужно, переписаны id через запятую... Они не удаляются и все! :(
Почему такое может быть?
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33515939
Фотография Duke1999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
какую ошибку выдает?
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33516207
Maksim UM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
может id без кавычек попробовать...
Код: plaintext
1.
$query = "DELETE FROM table WHERE id IN ($list)";
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33516277
Тупой!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пробовал и с кавычками и без кавычек - результиат тот же...
Ошибку НЕ выдает! Все проглатывает, но из таблицы ничего не удаляется! :(
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33516322
Фотография Duke1999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mysql_query($query) or die(mysql_error());
есть ошибка?
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33516405
Фотография Robert Tappan Moris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтоб очистить совесть рекомендую заменить
Код: plaintext
1.
2.
$sql = "DELETE FROM `$TblName` WHERE `$Field` IN ($List)";
mysql_query($sql);
на
Код: plaintext
1.
echo "DELETE FROM `$TblName` WHERE `$Field` IN ($List)";
ну а дальше остается попробовать скормить эту строку phpMyAdmin и посмотреть что он сделает или скажет.
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33517138
DocAl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подумалось об использовании CONTRAINT с ON DELETE CASCADE...
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33517182
Тупой!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем спасибо! :)
Мой косяк - плохо соображаю что делаю уже...
Выполняю $query = "DELETE FROM table WHERE id IN ($list)"; но это же не запрос, просто присвоил переменной $query и все (поэтому и нет ошибки MySQL никакой)! :)
Просто конструкция "mysql_query($query) or die(mysql_error());" вынесена в отедльную функцию "SQLResult" - и поэтому надо писать

$query = SQLResult("DELETE FROM table WHERE id IN ($list)");
что я пропустил мимо! :) Сам не пойму, как просмотрел...

Простите за невнимательность!
Все работает...
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33517266
DocAl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А всё таки, подумайте о предложенном мною варианте.
Вот пример:
Создаём таблицу
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE `test` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `name` varchar( 255 ) default '',
  `parent` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `parent` (`parent`),
  CONSTRAINT `test_ibfk_1` FOREIGN KEY (`parent`) REFERENCES `test` (`id`) ON DELETE CASCADE
) TYPE=InnoDB
Временно отключаем проверку ссылочной целостности и вносим корневой элемент:
Код: plaintext
1.
2.
3.
SET FOREIGN_KEY_CHECKS =  0 ;
INSERT INTO `test` VALUES ( 0 ,'home', 0 );
SET FOREIGN_KEY_CHECKS =  1 ;
Добавляем элементы:
Код: plaintext
1.
2.
3.
INSERT INTO `test` (`name`,`parent`) VALUES ('tld1', 0 );
INSERT INTO `test` (`name`,`parent`) VALUES ('1-tld1', 1 );
INSERT INTO `test` (`name`,`parent`) VALUES ('1-1-tld1', 2 );
Содержимое таблицы:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT * FROM `test`;
+----+----------+--------+
| id | name    | parent  |
+----+----------+--------+
|   0  | home     |       0  |
|   1  | tld1     |       0  |
|   2  |  1 -tld1   |       1  |
|   3  |  1 - 1 -tld1 |       2  |
+----+----------+--------+
А вот и запрос на удаление:
Код: plaintext
1.
DELETE FROM `test` WHERE id= 1 ;
Содержимое таблицы после удаления:
Код: plaintext
1.
2.
3.
4.
5.
+----+------+--------+
| id | name | parent |
+----+------+--------+
|   0  | home |       0  |
+----+------+--------+
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33517496
Фотография Robert Tappan Moris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как я поминаю, DocAl, Вы предлагаете сделать таблицу ссылающую на саму себя?

Если да и это действительно работает, то снимаю перед Вами шляпу. Такое решение получается перекладывает обязанность искать подчиненные узлы в удаляемом узле полностью на СУБД, а не на скрипт, которому приходится делать множество рекурсивных обращений к таблице. Пожалуй такое решение стоит считать единсвенно правильным ! =)
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33517570
Тупой!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DocAl очень красивое решение, но мне пока рановато видимо! Говорю же - с базами недавно работаю!
Может что почитать посоветуешь редкое и полезное?
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33517779
DocAl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Robert Tappan MorisКак я поминаю, DocAl, Вы предлагаете сделать таблицу ссылающую на саму себя?

Если да и это действительно работает, то снимаю перед Вами шляпу. Такое решение получается перекладывает обязанность искать подчиненные узлы в удаляемом узле полностью на СУБД, а не на скрипт, которому приходится делать множество рекурсивных обращений к таблице. Пожалуй такое решение стоит считать единсвенно правильным ! =)
Именно так. Единственное, что нельзя сделать таким способом полностью автоматически, это изменение id верхней записи с автоматическим обновлением parent у всех, ей принадлежащих. Но, во-первых, сложно представить себе ситуацию, в которой это могло бы практически потребоваться, во-вторых, реализовать это можно простым запросом, а учитывая, что InnoDB поддерживает транзакции, легко сделать так, чтобы ссылочная целостность при таком изменении также контролировалась движком базы.
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33517781
DocAl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тупой!DocAl очень красивое решение, но мне пока рановато видимо! Говорю же - с базами недавно работаю!
Может что почитать посоветуешь редкое и полезное?
А вот посоветовать почитать что-либо, кроме официальной документации на сайте, не могу...(
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33518445
Фотография Robert Tappan Moris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DocAl
Именно так. Единственное, что нельзя сделать таким способом полностью автоматически, это изменение id верхней записи с автоматическим обновлением parent у всех, ей принадлежащих. Но, во-первых, сложно представить себе ситуацию, в которой это могло бы практически потребоваться, во-вторых, реализовать это можно простым запросом, а учитывая, что InnoDB поддерживает транзакции, легко сделать так, чтобы ссылочная целостность при таком изменении также контролировалась движком базы.

Пара вопросов:
Простите, но зачему изменять поле id верхней записи, ведь поле автоинкрементное? Разве что сортировка при выборке делается по этому полю, но это было бы не правильно, если важен порядок записей. На мой взглять лучше добавить поле, по которому будут сортироваться записи (и редактировать проще, и головняка никакого).


Даже если предположить необходимость изменять поле id верхней записи можно сделать за 3 шага без проблем со ссылочной целостностью:
1) Вставлять в таблицу новую "верхнюю" запись (копию изменяемой).
2) Одним update'ом перевести все дочерние записи на вставленную.
3) Прибить оригинал записи.
...
Рейтинг: 0 / 0
PHP + MySQL: удалить с учетом иерархии...
    #33518497
DocAl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Именно так, я и написал, и нужно редко, и решается просто, но не полностью автоматически. А вот внешний ключ на другую таблицу может и обновление автоматом проводить.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP + MySQL: удалить с учетом иерархии...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]