powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Триггеры и наследование
15 сообщений из 15, страница 1 из 1
Триггеры и наследование
    #35545390
Pankon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть базовая таблица.
Эту базовую таблицу наследуют таблицы "наследники".

Написал триггер(Insert) для базовой таблицы. При вставке в одной из таблиц наследников - триггер в базовой таблице не срабатывает. Есть ли возможность заставить триггер заработать (ну или другое решение)?
...
Рейтинг: 0 / 0
Триггеры и наследование
    #35545697
glebofff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PankonЕсть базовая таблица.
Эту базовую таблицу наследуют таблицы "наследники".

Написал триггер(Insert) для базовой таблицы. При вставке в одной из таблиц наследников - триггер в базовой таблице не срабатывает. Есть ли возможность заставить триггер заработать (ну или другое решение)?

Самый простой вариант - вешать триггер на каждую таблицу.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Триггеры и наследование
    #39187908
Valentine_vaia
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Перевожу проект с PostgreSQL версии 7.4 на версию 9.2.
В БД используется наследование. Несколько таблиц наследуют родительскую, все лежат в разных схемах БД. На каждую таблицу созданы триггеры.
Возникает интересная ситуация при удалении записи из родительской таблицы под разными версиями:
версия 7.4 - всё корректно работает.
версия 9.2 - отмена удаления записи, из-за ошибки выполнения функции по триггеру дочерней таблицы.

Оказывается, разработчик БД предусмотрел проверку в функции триггера дочерней таблицы - если запись из родительской еще не удалена, то говорим что не можем удалить запись из дочерней таблицы.

Возникает несколько вопросов:

1) Как изменилась последовательность выполнения триггеров в таблицах, участвующих в наследовании? Как работало раньше и что изменилось?
2) Может идет параллельное выполнение триггерных функций? и как добиться старого поведения БД?
3) Может дело при работе в сессии и разными схемами, или выполнение транзакций?
4) Можно ли настроить сервер БД и на какие параметры нужно смотреть чтобы выяснить режим работы с транзакциями, триггерами??

Заметьте, пользователь БД пытается удалить только запись из родительской таблицы. Остальное делает сама БД.
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39187921
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valentine_vaia,

"ты не мудри, ты пальцем покажи" ((с)норот)

скорее всего никак не изменилось
и что значит "только из родительской" -- вы там так и пишете:
Код: sql
1.
 FROM ONLY 


или себе что--то навоображали ?

вот и гадай тут, с запотевшим шаром
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39187956
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valentine_vaiaВ БД используется наследование.
-1 imho
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188458
Valentine_vaia
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

извините, сама понимаю что трудно понять.

Привожу пример:

4 схемы: sh0, sh1, sh2, sh3
В каждой есть таблица, участвующая в наследовании: tab0 - родительская, tab1, tab2, tab3 - дочерние от tab0
В таблице sh3.tab3 хранится данные по объекту, например:
Код: sql
1.
2.
3.
4.
5.
6.
id |tab | idfkp
-------------
1|'sh0.tab0'|
2|'sh0.tab0'|
3|'sh0.tab0'|2
54|'sh1.tab1'|



Есть 2 триггерные функции после удаления записи из таблицы: tab0_adr9() и tab3_adr9()

Для каждой из таблиц создаются триггеры:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE TRIGGER tab0_adr9
    AFTER DELETE ON tab0
    FOR EACH ROW
    EXECUTE PROCEDURE tab0_adr9('sh0.tab0');
	
CREATE TRIGGER tab1_adr9
    AFTER DELETE ON tab1
    FOR EACH ROW
    EXECUTE PROCEDURE sh0.tab0_adr9('sh1.tab1');
		
CREATE TRIGGER tab2_adr9
    AFTER DELETE ON tab2
    FOR EACH ROW
    EXECUTE PROCEDURE sh0.tab0_adr9('sh2.tab2');
	
---
CREATE TRIGGER tab3_adr9
    AFTER DELETE ON tab3
    FOR EACH ROW
    EXECUTE PROCEDURE tab3_adr9();




Пытаемся удалить объект из БД: удаляем запись из tab0 с id = 1 , например, должны удалится связанные записи в дочерних таблицах.

Вот код самих триггерных функций:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
----
--sh0.tab0_adr9('sh2.tab2') -- функция только для проставления флага, если удаляемый объект последний в цепочке был
----------
CREATE FUNCTION tab0_adr9() RETURNS "trigger"
    AS '
DECLARE
 cmnd text;
BEGIN
-- comment
 IF TG_NARGS=0 OR TG_ARGV[0]=''sh0.tab0'' THEN -- if table-parents
  UPDATE sh0.tab0 SET fl=true WHERE id=OLD.idfkp AND NOT EXISTS
    (SELECT * FROM sh0.tab0 WHERE idfkp=OLD.idfkp); -- set "fl" where somewhere
 ELSE
  cmnd := ''UPDATE '' || TG_ARGV[0] || '' SET fl=true WHERE id='' || trim(OLD.idfkp::text)
       || '' AND NOT EXISTS(SELECT * FROM '' || TG_ARGV[0] || '' WHERE idfkp='' || trim(OLD.idfkp::text) || '')'';
  EXECUTE cmnd;
 END IF;
 RETURN NEW;
END;
'
    LANGUAGE plpgsql;
---
--sh3.tab3_adr9() -- собственно, функция из-за которой удаление записи сворачивается
---------------
CREATE FUNCTION tab3_adr9() RETURNS "trigger"
    AS '
DECLARE
 cmnd        text;
 rec         RECORD;
 rstxt       text;
BEGIN
 cmnd := ''SELECT id FROM ONLY '' || OLD.tab || '' WHERE id='' || trim(OLD.id::text); -- в поле tab хранится название таблицы, из которой удаляем, в данном случае 'sh0.tab0' 
 FOR rec IN EXECUTE cmnd
 LOOP
  rstxt := rec.id;
  IF rec.id = OLD.id THEN -- Если запись существует
   rstxt := rstxt || '' in ''  || OLD.tab;
  RAISE EXCEPTION ''EXIST rec.id = OLD.id = %'',rstxt; -- То выдаем сообщение об ошибке, например, EXIST rec.id = OLD.id = 1
  END IF;
  EXIT;
 END LOOP;
 RETURN OLD;
END;
'
    LANGUAGE plpgsql;



Под PostgreSQL 7.4 все корректно отрабатывает.
Под PostgreSQL 9.2 откатывает удаление из-за EXCEPTION: EXIST rec.id = OLD.id = 1

Из-за чего это происходит? Почему в версии 9.2 он видит уже якобы удаленный объект из sh0.tab0?
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188510
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valentine_vaia,

покажите код, которым вызываете удаление .
авторудаляем запись из tab0 с id = 1,
покажите код , который вызывает (возможно каскадом) удаление из tab3


не показывайте не schema--квалифаед кода. это дурной тон дурных отцов--основателей.

и с чего вы взяли, что что--то удаляет из дочерних ? у вас что, одни и те же данные разнесены во все дочерние и основную ?

и есть большое сомнение, что вызов в after DELETE триггере строчки RETURN NEW; не уронит вам всё нахер гораздо раньше, чем произойдёт что--то ещё. Т.е. я не уверен, что вы показываете нужные куски кода (схему показывайте всегда).
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188786
Valentine_vaia
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

Код: sql
1.
 DELETE FROM sh0.tab0 WHERE id = 1



Может я неправильно понимаю. Если удаляется запись из родительской таблицы, разве не удаляются данные по этой записи у дочерних таблиц?

БД разрабатывала не я. И сама обратила внимание на метку INHERITS при создании таблиц только когда не понимала "куда деваются записи из других таблиц?" (sh1.tab1, sh2.tab2, sh3.tab3), если удаляем только из sh0.tab0.. (когда это работает в PostgreSQL v7.4)
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188795
Valentine_vaia
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq у вас что, одни и те же данные разнесены во все дочерние и основную ?

Детально не изучала, слишком много таблиц и данных. Но вроде везде в дочерних id записи присутствует(

можете дать ссылку на материалы по наследованию? поверхностно я уже изучила из документации и других статей. Мне интересен механизм взаимодействия родительской и дочерних таблиц при добавлении записи, удалении.
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188819
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valentine_vaiaqwwq,

Код: sql
1.
DELETE FROM sh0.tab0 WHERE id = 1



Может я неправильно понимаю. Если удаляется запись из родительской таблицы, разве не удаляются данные по этой записи у дочерних таблиц?
вы неправильно понимаетею то, что написано, означает "удалить все записи из [всей] иерархии sh0.tab0.

а "удалить записи из родительской таблицы" пишется так:

Код: sql
1.
DELETE FROM ONLY sh0.tab0 WHERE id = 1




Valentine_vaiaБД разрабатывала не я. И сама обратила внимание на метку INHERITS при создании таблиц только когда не понимала "куда деваются записи из других таблиц?" (sh1.tab1, sh2.tab2, sh3.tab3), если удаляем только из sh0.tab0.. (когда это работает в PostgreSQL v7.4) просто совсем не обязательно записи с одинаковым id присутствуют во всех (или хотя бы ещё 1--й) таблицах иерархии.

вообще--то говоря, судя по назначению таблицы таб3 -- заданный ид должен принадлежать конкретной какой--то одной таблице иерархии. т.е. ид должен видимо лежать в одной и только одной таблице. могу врать -- отсюда всего не видно.

У вас вполне может быть ошибка данных -- что-то в 9.2. вставили против заложенной разработчиком логики, без поддержки (в обход) логической целостности -- и теперь бьётесь с логикой, которой не соответствуют вставленные данные.
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188828
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valentine_vaiaqwwq у вас что, одни и те же данные разнесены во все дочерние и основную ?

Детально не изучала, слишком много таблиц и данных. Но вроде везде в дочерних id записи присутствует(

можете дать ссылку на материалы по наследованию? поверхностно я уже изучила из документации и других статей. Мне интересен механизм взаимодействия родительской и дочерних таблиц при добавлении записи, удалении.ищите в приложении или БД логику, которой вставляете и апдейтите записи иерархии -- авось прояснеет устройство встроенной логики БД.

или приводите полностью определенный код со схемами, а не огрызки пждампа (порождения моральных уродов--печально известных как "отцы--основатели") , где задание схемы (set search path)) отделено от описания объектов пространственно, а вы всю последовательность и не приводите.
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188929
Valentine_vaia
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

в общем, я не права.

Построила наглядную схему наследования, убедилась что tab3 не участвует в наследовании.
Оказывается, удаление записи происходит по правилу
Код: sql
1.
2.
3.
CREATE RULE name AS ON DELETE
    TO sh0.tab0 
    DO DELETE FROM sh3.tab3 WHERE id = old.id



переформулирую изначальный вопрос:

Почему в старой версии все данные удалялись, а в новой нет?
Есть ли разница между последовательностью выполнения удаления записи из sh0.tab0 и выполнения правила по удалению следом записи из sh3.tab3?
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39188972
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valentine_vaia,

http://www.postgresql.org/docs/9.2/static/sql-createrule.html
авторIf neither ALSO nor INSTEAD is specified, ALSO is the default.

судя по всему -- проблема в очередности этого ALSO . скажем в 7. сначала удалялось из самой, а потом отрабатывало rule , а в вашем случае триггер на срабатывание rule отрабатывает раньше чем само удаление.

9.2 The transformation happens before the execution of the commands starts.
хотя для 7.2 это ,якобы, в случае апдейта/делета, было так же:
7.2 otherwise it is done after the original query in the case of ON INSERT, or before the original query in the case of ON UPDATE or ON DELETE.

сделайте для пробы вместо rule -- after delete триггер. (неудобство -- надо вешать триггер на каждую таблицу иерархии, в отличии от руле, которое скорее вешается на команду, чем на событие записи). тогда гарантировано очистка таб3 будет генерироваться after события delete из основной. И видится эти записи в таблицах уже, в момент проверки, не будут.
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39189018
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valentine_vaiaБД разрабатывала не я
тогда вам тяжело(
http://www.databaseanswers.org/data_models/
...
Рейтинг: 0 / 0
Триггеры и наследование
    #39191085
Valentine_vaia
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq
сделайте для пробы вместо rule -- after delete триггер.

Да, это самый очевидный вариант. Сделала) Теперь работает нормально. Спасибо большое!
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Триггеры и наследование
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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