Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Триггер, рекурсивный delete, есть грабли?
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Первый раз работаю с триггерными функциями, почитал мануал, что-то попробовал... есть дерево: Код: plaintext 1. 2. 3. 4. 5. 6. Хочу сделать удаление всех потомков при удалении элемента Код: plaintext 1. 2. 3. 4. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. Вопрос1... есть тут какие-нибудь грабли и не спорол ли я чушь? Вроде-бы всё работает правильно, но как-то довольно медленно(в принципе не критично но странно)... Обход дерева селектами идёт ГОРАЗДО быстрее, что мне кажется странным... Вопрос2 - можно ли определить, первый ли это делит или нет? на событие ПОСЛЕ удаления тоже хотелось-бы повесить тригер, чтоб он делал апдейт пары полей в этой-же таблице но только при удаление элеемента, а при рекурсивном удалении потомков не делал?.. спасибо ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.08.2006, 18:50 |
|
||
|
Триггер, рекурсивный delete, есть грабли?
|
|||
|---|---|---|---|
|
#18+
про время выполнения вопрос снимается... делал на тестовой странице которая не была нормально проиндексирована, на боевой таблице отработало шустро :) Остается второй вопрос... можно как-то определить, запущен ли DELETE запросом или-же он выполнен в тригерной функции... можно конечно делать апдейт после удаления каждого потомка, но это получится куча лишних апдейтов, некрасиво и дольше... я слабо понял что значит per-statement, может как раз если сделать тип тригера per-statement, то это будет то что надо, или нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.08.2006, 20:11 |
|
||
|
Триггер, рекурсивный delete, есть грабли?
|
|||
|---|---|---|---|
|
#18+
RomanVKпро время выполнения вопрос снимается... делал на тестовой странице которая не была нормально проиндексирована, на боевой таблице отработало шустро :) Остается второй вопрос... можно как-то определить, запущен ли DELETE запросом или-же он выполнен в тригерной функции... можно конечно делать апдейт после удаления каждого потомка, но это получится куча лишних апдейтов, некрасиво и дольше... я слабо понял что значит per-statement, может как раз если сделать тип тригера per-statement, то это будет то что надо, или нет? 1. мне кажется ваш велосипед будет хуже стандартного FK с условием ON DELETE CASCADE (который тоже порождает триггер , но триггер не "совсем обычный", а создаваемый модификатором CONSTRAINT CREATE CONSTRAINT TRIGGER .... причем триггерная ф-я будет у вас системной, написанной видимо на C и вероятно - более быстрой. 2. в стейтмент риггере вы не знаете OLD, (вернее DELETED) и поэтому вам придется делать что-то вида 2.1. DELETE FROM fmtest WHERE NOT EXISTS(SELECT * FROM fmtest f WHERE f.id = fmtest.pid) (в принципе это можно было бы делать через лефт джойн, но делете в пг не поддерживает синтаксиса удаления из внешнего джойна (примерно такого): 2.2. DELETE f.* FROM fmtest f LEFT JOIN fmtest f1 ON f1.id = f.pid WHERE f1.id IS NULL (по крайней мере я не знаю, как его записать при помощи фичи USING ) и посему придется делать что-то наподобие 2.3 DELETE fmtest WHERE id IN (SELECT f.id FROM fmtest f LEFT JOIN fmtest f1 ON f1.id = f.pid WHERE f1.id IS NULL) что вряд ли быстрее 2.1. (надо смотреть) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.08.2006, 10:53 |
|
||
|
Триггер, рекурсивный delete, есть грабли?
|
|||
|---|---|---|---|
|
#18+
А разве можно делать вторичный ключ на колонку в этой-же таблице? Мне почему-то казалось, что нет... правда не пробовал... мне почему-то сама эта идея казалась абсурдной... :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.08.2006, 19:03 |
|
||
|
Триггер, рекурсивный delete, есть грабли?
|
|||
|---|---|---|---|
|
#18+
4321 Отлично, оказывается можно, большое спасибо ... Вот ещё неизвестно сколько без этого совета жил-бы и не знал что внешним ключем колонки можно делать первичный ключ той-же таблицы.... :) Это как раз то, что доктор прописал :) Правда всё равно остается открытым вопрос по поводу того, что тригерная функция, которая идет после удаления сообщения, вызывается и делает апдейт после удаления каждого потомка... Как сделать чтобы при обычном делите апдейт(нужно апдейтить время последнего сообщения(последнего потомка) для корневого сообщения) делался только при удалении того что указано в делите и не делался при каскадном удалении всех потомков... хотя по скорости и так вполне устраивает... но чисто эстетически не очень красиво.. ненужная избыточность... :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.08.2006, 21:44 |
|
||
|
Триггер, рекурсивный delete, есть грабли?
|
|||
|---|---|---|---|
|
#18+
RomanVKКак сделать чтобы при обычном делите апдейт(нужно апдейтить время последнего сообщения(последнего потомка) для корневого сообщения) делался только при удалении того что указано в делите и не делался при каскадном удалении всех потомков... хотя по скорости и так вполне устраивает... но чисто эстетически не очень красиво.. ненужная избыточность... :)можно сделать грубо и зримо - запретить делет из таблицы напрямую. и написать ХП для удаления, которая, кроме того, вместо триггера будет апдейтить вашу стороннюю таблицу. можно видимо сделать через любую переменную сеанса (в частности, в plpgsql, - через создание временной таблицы или счетчика -в качестве флага "не первости отработки триггера" - с обрабоботкой исключения в триггере - если таблица/счетчик еще не созданы), например, - пользуя языки, в которых переменные сеанса создаются лехко и непринужденно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.08.2006, 10:32 |
|
||
|
Триггер, рекурсивный delete, есть грабли?
|
|||
|---|---|---|---|
|
#18+
Кстати - переменную сеанса можно сделать и в простом pgplsql и даже sql я тут недавно для себя открыл если в файле postgresql.conf в разделе #--------------------------------------------------------------------------- # CUSTOMIZED OPTIONS #--------------------------------------------------------------------------- добавить свой класс : # list of custom variable class names custom_variable_classes = 'session' то после рестарта сервера можно создавать и использовать сессионные переменные. Ограничение только одно - эта переменная содержит только строки.. к примеру: select current_setting('session.var1') -> unset select set_config('session.var1',100,false) -> set session.var1='100' select current_setting('session.var1') -> 100 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.08.2006, 11:44 |
|
||
|
|

start [/forum/topic.php?fid=53&gotonew=1&tid=2006172]: |
0ms |
get settings: |
7ms |
get forum list: |
16ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
55ms |
get topic data: |
11ms |
get first new msg: |
8ms |
get forum data: |
4ms |
get page messages: |
51ms |
get tp. blocked users: |
2ms |
| others: | 265ms |
| total: | 423ms |

| 0 / 0 |
