Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Про триггеры (заранее пардон). / 7 сообщений из 7, страница 1 из 1
01.12.2005, 13:29
    #33410951
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Про триггеры (заранее пардон).
Что-то я почитал про триггеры в ПГ, и не понял как же мне сделать многострочный триггер... как обрадиться к рекордсету над которым произошли манипуляции?
Вот пример того что я хочу сделать, триггер должен отрабатывать набор строк вставленных таблицу "srcTable":
Код: plaintext
1.
2.
3.
4.
/* В реальности нижеприведенный запрос содержит агрегации и подзапросы */
INSERT INTO dstTable (field1, field2)
SELECT n.field1, n.field2 FROM NEW n LEFT JOIN dstTable d
WHERE d.field1 IS NULL AND d.field2 IS NULL
...
Рейтинг: 0 / 0
01.12.2005, 13:34
    #33410976
XM
XM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Про триггеры (заранее пардон).
Paul Chabinsky wrote:
> Что-то я почитал про триггеры в ПГ, и не понял как же мне сделать
> многострочный триггер... как обрадиться к рекордсету над которым
> произошли манипуляции?

Никак. Триггеры либо ROW-LEVEL - доступ к одной измененнной записи,
либо STATEMENT-LEVEL - без доступа к измененным записям.
Т.е. рекордсета нет в любом случае.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
01.12.2005, 13:38
    #33411007
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Про триггеры (заранее пардон).
Мда...
А правилами такое можно сделать?
...
Рейтинг: 0 / 0
01.12.2005, 13:43
    #33411024
XM
XM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Про триггеры (заранее пардон).
Paul Chabinsky wrote:
> Мда...
> А правилами такое можно сделать?

Врядли.
Хотя, в принципе, можно извратиться и в ROW-LEVEL триггере вносить PK
измененных записей во временную таблицу, а потом в STATEMENT-LEVEL
использовать эту инфу. :)

ЗЫ не проверял, так, первое что сходу придумалось.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
01.12.2005, 13:49
    #33411053
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Про триггеры (заранее пардон).
Задача то как раз в том чтоб триггер/что-то-еще, давало возможность многострочной обработки...

А если построчно делать темп, то почему построчно сразу не вставить просто и все :)

Все равно спасибо за помощь...
...
Рейтинг: 0 / 0
02.12.2005, 03:41
    #33412631
фффф
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Про триггеры (заранее пардон).
XM
... в принципе, можно извратиться и в ROW-LEVEL триггере вносить PK
измененных записей во временную таблицу, а потом в STATEMENT-LEVEL
использовать эту инфу. :)

Делал такую эмуляцию MSSQL after-триггеров с таблицами inserted/deleted. Геморрой большой - надо на каждую табличку зеркальную создавать, потом эта таблица пухнет - надо часто вакуумить её. Тестовый скрипт выкладываю:
Код: plaintext
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.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
create table teststmt (id serial primary key, d text);
create table teststmt_tr (pid int default pg_backend_pid(), inserted bool, data teststmt);
create view teststmt_inserted as
  select (data).id, (data).d
  from teststmt_tr
  where pid=pg_backend_pid() and inserted;
create view teststmt_deleted as
  select (data).id, (data).d
  from teststmt_tr a
  where pid=pg_backend_pid() and not inserted;

CREATE OR REPLACE FUNCTION tf_teststmt_stmt_process() RETURNS trigger LANGUAGE plpgsql AS $body$
DECLARE
  _rec teststmt%rowtype;
BEGIN
  if TG_LEVEL = 'ROW' then
    --collect 'inserted'/'deleted' rows
    if TG_OP = 'INSERT' or TG_OP = 'UPDATE' then
      insert into teststmt_tr(inserted, data) values (true, NEW);
    end if;
    if TG_OP = 'DELETE' or TG_OP = 'UPDATE' then
      insert into teststmt_tr(inserted, data) values (false, OLD);
    end if;
  else
    if TG_WHEN = 'AFTER' then
      --process set of rows
      for _rec in (select * from teststmt_inserted) loop
        raise INFO 'inserted : % %', _rec.id, _rec.d;
      end loop;
      for _rec in (select * from teststmt_deleted) loop
        raise INFO 'deleted : % %', _rec.id, _rec.d;
      end loop;
    end if;
    
    --cleanup before and after row processing
    delete from teststmt_tr where pid=pg_backend_pid();
    --vacuum teststmt_tr;
  end if;
  
  return NEW;
END;
$body$;

CREATE TRIGGER teststmt_before_stmt BEFORE INSERT or UPDATE or DELETE
  ON teststmt FOR EACH STATEMENT
  EXECUTE PROCEDURE tf_teststmt_stmt_process();
CREATE TRIGGER teststmt_after_stmt AFTER INSERT or UPDATE or DELETE
  ON teststmt FOR EACH STATEMENT
  EXECUTE PROCEDURE tf_teststmt_stmt_process();
CREATE TRIGGER teststmt_after_row AFTER INSERT or UPDATE or DELETE
  ON teststmt FOR EACH ROW
  EXECUTE PROCEDURE tf_teststmt_stmt_process();

insert into teststmt(d) select 'hello';
insert into teststmt(d) select 'world';
insert into teststmt(d) select d||'!' from teststmt;
select * from teststmt;
select * from teststmt_tr;

update teststmt set d=d||'-upd';
select * from teststmt;
select * from teststmt_tr;

delete from teststmt;
select * from teststmt;
select * from teststmt_tr;
...
Рейтинг: 0 / 0
02.12.2005, 11:03
    #33413077
Paul Chabinsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Про триггеры (заранее пардон).
Спасибо, попробую...
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Про триггеры (заранее пардон). / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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