Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP + MySQL: удалить с учетом иерархии... / 20 сообщений из 20, страница 1 из 1
31.01.2006, 16:48
    #33513889
Тупой!
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Доброе время суток, 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
31.01.2006, 16:57
    #33513920
Duke1999
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
неплохой ник :)
а причем здесь php?
это запрос к SQL серверу "УДАЛИТЬ ИЗ имя_таблицы ГДЕ level = 1"
...
Рейтинг: 0 / 0
31.01.2006, 17:54
    #33514171
Тупой!
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Duke1999, спасибо! :)

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

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

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

Затем аналогично пробегаться по всем элементам массива с полученными ID в результате первого запроса и т.д... Но еще раз повторюсь - вложений может быть до черта великого! :( Нужен некий цикл максимально оптимизированный... Я не могу больше уследить за всеми вложениями - поплыли мозги совершенно...
Потому и прошу помощи!!!
...
Рейтинг: 0 / 0
31.01.2006, 18:56
    #33514398
Robert Tappan Moris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Удалять из таблицы можно указывая список значений:
Код: 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
31.01.2006, 18:58
    #33514405
Robert Tappan Moris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Только строчку
Код: plaintext
1.
$DelId =  1 ;
нужно удалить =)
...
Рейтинг: 0 / 0
01.02.2006, 11:57
    #33515493
Тупой!
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
ВСЕ ОТЛИЧНО! Все супер! ЭТО ТО, что мне нужно было... ОГРОМНОЕ спасибо...

Единственное - не хочет у меня MySQL выполнять
$query = "DELETE FROM table WHERE `id` IN ($list)";
хотя в $list -все как нужно, переписаны id через запятую... Они не удаляются и все! :(
Почему такое может быть?
...
Рейтинг: 0 / 0
01.02.2006, 13:43
    #33515939
Duke1999
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
какую ошибку выдает?
...
Рейтинг: 0 / 0
01.02.2006, 14:39
    #33516207
Maksim UM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
может id без кавычек попробовать...
Код: plaintext
1.
$query = "DELETE FROM table WHERE id IN ($list)";
...
Рейтинг: 0 / 0
01.02.2006, 14:56
    #33516277
Тупой!
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Пробовал и с кавычками и без кавычек - результиат тот же...
Ошибку НЕ выдает! Все проглатывает, но из таблицы ничего не удаляется! :(
...
Рейтинг: 0 / 0
01.02.2006, 15:06
    #33516322
Duke1999
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
mysql_query($query) or die(mysql_error());
есть ошибка?
...
Рейтинг: 0 / 0
01.02.2006, 15:22
    #33516405
Robert Tappan Moris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Чтоб очистить совесть рекомендую заменить
Код: 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
01.02.2006, 18:30
    #33517138
DocAl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Подумалось об использовании CONTRAINT с ON DELETE CASCADE...
...
Рейтинг: 0 / 0
01.02.2006, 18:40
    #33517182
Тупой!
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Всем спасибо! :)
Мой косяк - плохо соображаю что делаю уже...
Выполняю $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
01.02.2006, 19:02
    #33517266
DocAl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
А всё таки, подумайте о предложенном мною варианте.
Вот пример:
Создаём таблицу
Код: 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
01.02.2006, 20:23
    #33517496
Robert Tappan Moris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP + MySQL: удалить с учетом иерархии...
Как я поминаю, DocAl, Вы предлагаете сделать таблицу ссылающую на саму себя?

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

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

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


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


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