[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Mysql триггер для удаление дерева
mysql_trigger_info
Привет, подскажите пожалуйста как правильно написать триггер чтоб при удалении строки удалялись все строки в этой же таблице со значением `parent` = id удаленной строки.
Ранее я делал удаление каскадным удалением, вот так:

ALTER TABLE `tree`
ADD CONSTRAINT `tree_parent` FOREIGN KEY (`parent`) REFERENCES `tree` (`id`) ON DELETE CASCADE;

Но узнал что есть дерево больше 15 строк то выскакивает ошибка #3008 - Foreign key cascade delete/update exceeds max depth of 15.

Мне нужно написать триггер который будет удалять полностью дерево, подскажите пожалуйста код триггера, триггер ниже не работает, ошибка #1442 - Can't update table 'delivery2' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

CREATE TRIGGER `tree_parent` BEFORE DELETE ON `tree`
FOR EACH ROW DELETE FROM tree WHERE parent = old.id
walerus
У Вас видимо рекурсия получается по этому он и ругается на вложенность более 15 уровней
mysql_trigger_info
Цитата (walerus @ 17.08.2022 - 18:44)
У Вас видимо рекурсия получается по этому он и ругается на вложенность более 15 уровней

На самом деле я хотел протестировать работает ли он с очень большой вложенностью.
Добавил большую вложенность:

for($i=0;$i<10000;$i++){
if($i>0){
mysqli_query($db,"INSERT `tree` SET `parent`=$parent, `price`=".mt_rand(1,9999));
} else {
mysqli_query($db,"INSERT `tree` SET `price`=".mt_rand(1,9999));
}
$parent=mysqli_insert_id($db);
}

И напоролся на данную проблему с удалением если вложенность больше 15.
Подскажите можно ли написать триггер который будет удалять большую вложенность? или только своей функцией можно реализовывать удаление - рекурсивной функцией?
walerus
Да, видимо придется писать свой обработчик, так как мускуль не дает обработку больше чем 15ть.

Можно попробовать сделать иначе, что бы сильно не "замарачиваться", добавить например поле "deleted" и триггером это дело все помечать, после запроса на удаление, как отработает триггер, удалить все items, where delete = true.

Это один из вариантов.
kirik
Цитата
добавить например поле "deleted" и триггером это дело все помечать, после запроса на удаление

Не поможет, будет та же ошибка.

Цитата
или только своей функцией можно реализовывать удаление - рекурсивной функцией?

Можете попробовать написать триггер на AFTER DELETE в котором рекурсивно удалите все записи.
walerus
AFTER DELETE - так же не поможет, будет та же рекурсия глубже 15го уровня, на сколько я понял из прочитанного, нельзя триггер вешать на одну и ту же таблицу, в которой происходит удаление...
- "что то там" нарушает логику транзакций

P.S.

Попробовал через метку delete все работает, правда без триггера, но кто нам мешает написать метод обработки и кидать в него нужным ID ???

UPDATE 
new_table_test_php SET deleted = true
WHERE id IN (

SELECT dd.id FROM
(
select t.id , @pv:=t.parent as parent
from (select * from new_table_test_php order by id desc) t
join
(select @pv:=6)tmp
where t.id=@pv and t.parent is not null) as dd)


(select @pv:=6)tmp - здесь указывается какая строка удаляется и рекурсивно от нее все parents, в данном случае - с 6й строки


После этого запроса все нужные нам Items будут помечены

id, price, parent, deleted
'1', '6080', NULL, '0'
'2', '5965', '1', '1'
'3', '6819', '2', '1'
'4', '1387', '3', '1'
'5', '8084', '4', '1'
'6', '564', '5', '1'
'7', '2436', '6', '0'
'8', '7525', '7', '0'
'9', '4646', '8', '0'
'10', '334', '9', '0'


И теперь мы можем их удалить
DELETE FROM new_table_test_php WHERE deleted = true;


зы: взято от сюда тыц
mysql_trigger_info
Цитата (walerus @ 19.08.2022 - 12:15)
AFTER DELETE - так же не поможет, будет та же рекурсия глубже 15го уровня, на сколько я понял из прочитанного, нельзя триггер вешать на одну и ту же таблицу, в которой происходит удаление...
- "что то там" нарушает логику транзакций

P.S.

Попробовал через метку delete все работает, правда без триггера, но кто нам мешает написать метод обработки и кидать в него нужным ID ???

UPDATE 
new_table_test_php SET deleted = true
WHERE id IN (

SELECT dd.id FROM
(
select t.id , @pv:=t.parent as parent
from (select * from new_table_test_php order by id desc) t
join
(select @pv:=6)tmp
where t.id=@pv and t.parent is not null) as dd)


(select @pv:=6)tmp - здесь указывается какая строка удаляется и рекурсивно от нее все parents, в данном случае - с 6й строки


После этого запроса все нужные нам Items будут помечены

id, price, parent, deleted
'1', '6080', NULL, '0'
'2', '5965', '1', '1'
'3', '6819', '2', '1'
'4', '1387', '3', '1'
'5', '8084', '4', '1'
'6', '564', '5', '1'
'7', '2436', '6', '0'
'8', '7525', '7', '0'
'9', '4646', '8', '0'
'10', '334', '9', '0'


И теперь мы можем их удалить
DELETE FROM new_table_test_php WHERE deleted = true;


зы: взято от сюда тыц

Большое спасибо smile.gif
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.