Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / AFTER TRIGGER / 22 сообщений из 22, страница 1 из 1
19.01.2022, 11:54
    #40127725
PaulWist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Братья!

Как обратиться к псевдо таблице в After Trigger-е, что бы связать её с основной таблицей? (если это возможно, либо подскажите лайфхак)
...
Рейтинг: 0 / 0
19.01.2022, 12:03
    #40127730
SQL*Plus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist
Братья!

Как обратиться к псевдо таблице в After Trigger-е, что бы связать её с основной таблицей?
(если это возможно, либо подскажите лайфхак)

Расскажите, что такое "псевдо таблица" и где о ней можно почитать в документации Oracle.
...
Рейтинг: 0 / 0
19.01.2022, 12:04
    #40127731
dmdmdm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
After trigger for statement, очевидно?

Лучше задачу обозначьте.
А то обычно спрашивают про способ решения, без уяснения задачи преждевременно его обсуждать.
...
Рейтинг: 0 / 0
19.01.2022, 12:07
    #40127733
SQL*Plus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
dmdmdm,

Не будем гадать.
Пусть ТС объяснит свою проблему "нормально, на гражданском языке" (с) Джентльмены удачи
...
Рейтинг: 0 / 0
19.01.2022, 12:21
    #40127739
PaulWist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
SQL*Plus

Расскажите, что такое "псевдо таблица" и где о ней можно почитать в документации Oracle.


ОК, не псевдотаблица, а Pseudorecords (пасевдозаписи) :OLD or the :NEW value

dmdmdmAfter trigger for statement, очевидно?

Лучше задачу обозначьте.
А то обычно спрашивают про способ решения, без уяснения задачи преждевременно его обсуждать.



Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
-- Табличка
create table test (f1 NUMBER NOT NULL ENABLE);

-- Табличка лога
create table test1 (f1 NUMBER NOT NULL ENABLE, f2 NVARCHAR2);

-- Заполняем
insert into test (f1) values (1);
insert into test (f1) values (1);
insert into test (f1) values (2);
insert into test (f1) values (2);

-- Модифицируем
update test set f1 = f1 



Что хочу: в табличку лога записать при update по одной записи из таблички test (distinct, те что бы там было две записи f1 = 1, 2), как это можно сделать в триггере?
...
Рейтинг: 0 / 0
19.01.2022, 12:44
    #40127745
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist

Что хочу: в табличку лога записать при update по одной записи из таблички test


уникальный индекс на test1, + exception

.....
stax
...
Рейтинг: 0 / 0
19.01.2022, 12:51
    #40127751
PaulWist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Stax

уникальный индекс на test1, + exception
.....
stax


Ммм, вы предлагаете создать в триггере уникальный индекс? неожиданно
...
Рейтинг: 0 / 0
19.01.2022, 13:27
    #40127760
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist
Stax

уникальный индекс на test1, + exception
.....
stax


Ммм, вы предлагаете создать в триггере уникальный индекс? неожиданно


почему в триггере,
создать индекс для таблички лога (тест1)
create unique index i on test1(f1);

в триггере обработать exception
или хинт insert /*+ ignore_row_on_dupkey_index

зы
+ разобратся с null для f1


.....
stax
...
Рейтинг: 0 / 0
19.01.2022, 13:43
    #40127767
PaulWist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Stax

почему в триггере,
создать индекс для таблички лога (тест1)
create unique index i on test1(f1);

в триггере обработать exception
или хинт insert /*+ ignore_row_on_dupkey_index

зы
+ разобратся с null для f1


.....
stax


Нет проблемы написать constraint, но он не заполнит табличку test1, мне надо выяснить какие записи из test.f1 были затронуты триггером, собственно в этом вопрос.
...
Рейтинг: 0 / 0
19.01.2022, 13:55
    #40127775
Алымов Анатолий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Создайте compound trigger. В after for each rows заполняешь коллекцию уникальную. В after statement обрабатываешь коллекцию.
...
Рейтинг: 0 / 0
19.01.2022, 14:10
    #40127783
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist

Нет проблемы написать constraint, но он не заполнит табличку test1, мне надо выяснить какие записи из test.f1 были затронуты триггером, собственно в этом вопрос.


Вам надо убрать дубликаты только для конкретного (текущего) оператора update?
если да то
1) 22423127 (не обязательно компаунд)
2) в логе + ид вставки (напр из последовательности)

.....
stax
...
Рейтинг: 0 / 0
19.01.2022, 14:11
    #40127784
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Алымов Анатолий
Создайте compound trigger. В after for each rows заполняешь коллекцию уникальную. В after statement обрабатываешь коллекцию.


например?
...
Рейтинг: 0 / 0
19.01.2022, 14:17
    #40127787
booby
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
...
Рейтинг: 0 / 0
19.01.2022, 14:51
    #40127796
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist

Что хочу: в табличку лога записать при update по одной записи из таблички test (distinct, те что бы там было две записи f1 = 1, 2), как это можно сделать в триггере?


При update из разных сессий distinct в табличке лога не получится.

SY.
...
Рейтинг: 0 / 0
19.01.2022, 14:53
    #40127800
ANB-ANB
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Код: 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.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
create table ANB_Compound_Trg_Test_Table
(
  id integer not null
 ,S01 varchar2(64)
 ,S02 varchar2(64)
 ,S03 varchar2(64)
 ,S04 varchar2(64)
 ,D01 date
 ,D02 date
 ,D03 date
 ,D04 date
 ,N01 number
 ,N02 number
 ,N03 number
 ,N04 number
)
tablespace TBS_Qrm_Data
/

create or replace trigger Trg$Cmp$ANB_Compound_Trg_Test_Table
for update or delete or insert on ANB_Compound_Trg_Test_Table
compound trigger

  -- Индекс
  v_Index binary_integer := 0;

  -- Строка с изменениями
  type T_Rec is record
  (
    Operation varchar2(4)-- Это чисто для примера и наглядности
    -- На самом деле триггер срабатывает на каждый оператор отдельно и везде доступны inserting, updating, deleting
    -- merge вызывает триггер 2 раза : сначала на insert, потом на update
    -- То есть это поле в массиве изменений не нужно
   ,R_Old ANB_Compound_Trg_Test_Table%rowtype
   ,R_New ANB_Compound_Trg_Test_Table%rowtype
  );

  -- Коллекция изменений
  type T_Table is table of T_Rec index by binary_integer;

  -- Переменные для строки и коллекции
  v_R T_Rec;
  v_T T_Table;

  before statement
  is
  begin
    -- v_T.delete; -- Это необязательно, т.к. каждый оператор сбрасывает внутренние переменные
    null;
  end before statement;
  
  before each row is
  begin
    -- Запоминать будем уже готовые поля
    null;
  end before each row;
  
  after each row
  is
  begin
    -- Запоминать будем уже готовые поля

    -- Индекс
    v_Index := v_Index + 1;

    -- Набьем строку
    v_R := null;
    if inserting then
      v_R.Operation := 'I';
    elsif updating then
      v_R.Operation := 'U';
    else
      v_R.Operation := 'D';
    end if;

    -- Запись до изменения
    v_R.R_Old.ID := :Old.ID;
    v_R.R_Old.S01 := :Old.S01;
    v_R.R_Old.S02 := :Old.S02;
    v_R.R_Old.S03 := :Old.S03;
    v_R.R_Old.S04 := :Old.S04;
    v_R.R_Old.D01 := :Old.D01;
    v_R.R_Old.D02 := :Old.D02;
    v_R.R_Old.D03 := :Old.D03;
    v_R.R_Old.D04 := :Old.D04;
    v_R.R_Old.N01 := :Old.N01;
    v_R.R_Old.N02 := :Old.N02;
    v_R.R_Old.N03 := :Old.N03;
    v_R.R_Old.N04 := :Old.N04;

    -- Запись после изменения
    v_R.R_New.ID := :New.ID;
    v_R.R_New.S01 := :New.S01;
    v_R.R_New.S02 := :New.S02;
    v_R.R_New.S03 := :New.S03;
    v_R.R_New.S04 := :New.S04;
    v_R.R_New.D01 := :New.D01;
    v_R.R_New.D02 := :New.D02;
    v_R.R_New.D03 := :New.D03;
    v_R.R_New.D04 := :New.D04;
    v_R.R_New.N01 := :New.N01;
    v_R.R_New.N02 := :New.N02;
    v_R.R_New.N03 := :New.N03;
    v_R.R_New.N04 := :New.N04;
    
    -- Сохраним строку в коллекцию
    v_T(v_Index) := v_R;

  end after each row;
  
  after statement
  is
  begin

    -- Собственно, тут и должна быть обработка изменений оператора
    -- Для примера просто напечатаем массив изменений
    
    DBMS_OutPut.Put_Line('---------------');
    DBMS_OutPut.Put_Line('after statement');
    DBMS_OutPut.Put_Line('---------------');
    DBMS_OutPut.Put_Line('');

    -- Прочитаем результат
    for i in nvl(v_T.First, 0) .. nvl(v_T.Last, -1) loop

      v_R := v_T(i);
      
      -- Чисто для примера просто напечатаем массив изменений, ничего с ним не делая
      DBMS_OutPut.Put_Line('i = '||i);
      DBMS_OutPut.Put_Line('Operation = '||v_R.Operation);
      DBMS_OutPut.Put_Line('Old.ID = '||v_R.R_Old.ID);
      DBMS_OutPut.Put_Line('Old.S01 = '||v_R.R_Old.S01);
      DBMS_OutPut.Put_Line('Old.S02 = '||v_R.R_Old.S02);
      DBMS_OutPut.Put_Line('Old.S03 = '||v_R.R_Old.S03);
      DBMS_OutPut.Put_Line('Old.S04 = '||v_R.R_Old.S04);
      DBMS_OutPut.Put_Line('Old.D01 = '||v_R.R_Old.D01);
      DBMS_OutPut.Put_Line('Old.D02 = '||v_R.R_Old.D02);
      DBMS_OutPut.Put_Line('Old.D03 = '||v_R.R_Old.D03);
      DBMS_OutPut.Put_Line('Old.D04 = '||v_R.R_Old.D04);
      DBMS_OutPut.Put_Line('Old.N01 = '||v_R.R_Old.N01);
      DBMS_OutPut.Put_Line('Old.N02 = '||v_R.R_Old.N02);
      DBMS_OutPut.Put_Line('Old.N03 = '||v_R.R_Old.N03);
      DBMS_OutPut.Put_Line('Old.N04 = '||v_R.R_Old.N04);
      DBMS_OutPut.Put_Line('New.ID = '||v_R.R_New.ID);
      DBMS_OutPut.Put_Line('New.S01 = '||v_R.R_New.S01);
      DBMS_OutPut.Put_Line('New.S02 = '||v_R.R_New.S02);
      DBMS_OutPut.Put_Line('New.S03 = '||v_R.R_New.S03);
      DBMS_OutPut.Put_Line('New.S04 = '||v_R.R_New.S04);
      DBMS_OutPut.Put_Line('New.D01 = '||v_R.R_New.D01);
      DBMS_OutPut.Put_Line('New.D02 = '||v_R.R_New.D02);
      DBMS_OutPut.Put_Line('New.D03 = '||v_R.R_New.D03);
      DBMS_OutPut.Put_Line('New.D04 = '||v_R.R_New.D04);
      DBMS_OutPut.Put_Line('New.N01 = '||v_R.R_New.N01);
      DBMS_OutPut.Put_Line('New.N02 = '||v_R.R_New.N02);
      DBMS_OutPut.Put_Line('New.N03 = '||v_R.R_New.N03);
      DBMS_OutPut.Put_Line('New.N04 = '||v_R.R_New.N04);
      DBMS_OutPut.Put_Line('------------------------------------------');
      DBMS_OutPut.Put_Line('');

    end loop;

  end after statement;

end Trg$Cmp$ANB_Compound_Trg_Test_Table;
/

-- Инициация теста
truncate table ANB_Compound_Trg_Test_Table
/
-- Все одной пачкой для наглядности
declare
begin

  -- Вставка новых записей

  -- Первый инсерт
  insert
  into ANB_Compound_Trg_Test_Table
  (
    id
   ,S01
   ,S02
   ,S03
   ,S04
   ,D01
   ,D02
   ,D03
   ,D04
   ,N01
   ,N02
   ,N03
   ,N04
  )
  select
    rownum id
   ,rownum * 1 S01
   ,rownum * 2 S02
   ,rownum * 3 S03
   ,rownum * 4 S04
   ,date'2020-01-01' + rownum + 10 D01
   ,date'2020-01-01' + rownum + 20 D02
   ,date'2020-01-01' + rownum + 30 D03
   ,date'2020-01-01' + rownum + 40 D04
   ,rownum * 10 N01
   ,rownum * 20 N02
   ,rownum * 30 N03
   ,rownum * 40 N04
  from
    dual
  connect by
    level <= 10;

  -- Второй инсерт
  insert
  into ANB_Compound_Trg_Test_Table
  (
    id
   ,S01
   ,S02
   ,S03
   ,S04
   ,D01
   ,D02
   ,D03
   ,D04
   ,N01
   ,N02
   ,N03
   ,N04
  )
  select
    rownum + 20 id
   ,rownum * 1 S01
   ,rownum * 2 S02
   ,rownum * 3 S03
   ,rownum * 4 S04
   ,date'2020-01-01' + rownum + 10 D01
   ,date'2020-01-01' + rownum + 20 D02
   ,date'2020-01-01' + rownum + 30 D03
   ,date'2020-01-01' + rownum + 40 D04
   ,rownum * 10 N01
   ,rownum * 20 N02
   ,rownum * 30 N03
   ,rownum * 40 N04
  from
    dual
  connect by
    level <= 5;

  -- Update
  update
    ANB_Compound_Trg_Test_Table
  set
    N01 = id * 100
   ,N02 = id * 200
   ,N03 = id * 300
   ,N04 = id * 400
  where
    id <= 10;
    
  -- Удаление
  delete
  from
    ANB_Compound_Trg_Test_Table
  where
    id <= 3;

  -- Merge
  merge
  into
    ANB_Compound_Trg_Test_Table D
  using
  (
  select
    rownum id
   ,rownum * 1000 S01
   ,rownum * 2000 S02
   ,rownum * 3000 S03
   ,rownum * 4000 S04
   ,date'2020-01-01' + rownum + 10 D01
   ,date'2020-01-01' + rownum + 20 D02
   ,date'2020-01-01' + rownum + 30 D03
   ,date'2020-01-01' + rownum + 40 D04
   ,rownum * 10 N01
   ,rownum * 20 N02
   ,rownum * 30 N03
   ,rownum * 40 N04
  from
    dual
  connect by
    level <= 5
  ) S
  on
  (
    D.ID = S.ID
  )
  when matched then
  update
  set
    D.S01 = S.S01
   ,D.S02 = S.S02
   ,D.S03 = S.S03
   ,D.S04 = S.S04
  when not matched then
  insert
  (
    D.id
   ,D.S01
   ,D.S02
   ,D.S03
   ,D.S04
   ,D.D01
   ,D.D02
   ,D.D03
   ,D.D04
   ,D.N01
   ,D.N02
   ,D.N03
   ,D.N04
  )
  values
  (
    S.id
   ,S.S01
   ,S.S02
   ,S.S03
   ,S.S04
   ,S.D01
   ,S.D02
   ,S.D03
   ,S.D04
   ,S.N01
   ,S.N02
   ,S.N03
   ,S.N04
  );

  commit;
end;
/
...
Рейтинг: 0 / 0
19.01.2022, 15:20
    #40127821
PaulWist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
ANB-ANB,

Отлично. Спасибо.

То есть, "псевдо таблицу" формируем "руками", хорошо... тогда вопрос: можно ли связать "псевдо таблицу" с исходной таблицей (select inner join) и в какой секции это можно сделать? (trigger for each row вольности типа select from таблица с триггером - не позволяет).
...
Рейтинг: 0 / 0
19.01.2022, 15:31
    #40127827
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist

Код: plsql
1.
2.
-- Модифицируем
update test set f1 = f1 



Что хочу: в табличку лога записать при update по одной записи из таблички test (distinct, те что бы там было две записи f1 = 1, 2), как это можно сделать в триггере?


повторно
если еще раз выполнить
update test set f1 = f1
в табличке лога сколько записей будет (2 or 4)?

.....
stax
...
Рейтинг: 0 / 0
19.01.2022, 15:46
    #40127832
PaulWist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Stax

повторно
если еще раз выполнить
update test set f1 = f1
в табличке лога сколько записей будет (2 or 4)?

.....
stax


По большому счёту это не важно 2 или 4 (был просто пример, что бы на пальцах рассказали как надо делать), нужен был принцип получения обработанных записей в триггере.
...
Рейтинг: 0 / 0
19.01.2022, 15:50
    #40127837
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist
Stax

повторно
если еще раз выполнить
update test set f1 = f1
в табличке лога сколько записей будет (2 or 4)?

.....
stax


По большому счёту это не важно 2 или 4 (был просто пример, что бы на пальцах рассказали как надо делать), нужен был принцип получения обработанных записей в триггере.


Писал разные вещи, но от ответа ушел
...
Рейтинг: 0 / 0
19.01.2022, 15:58
    #40127839
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWistнужен был принцип получения обработанных записей в триггере.

Обычно для таких задач используют триггера ON EACH ROW.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.01.2022, 16:01
    #40127841
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
PaulWist

По большому счёту это не важно 2 или 4

нет, ето важно
если 2, то нужен (желателен) индекс
если 4, индекс не нужен, реализовать через коллекцию


.....
stax
...
Рейтинг: 0 / 0
21.01.2022, 15:18
    #40128448
PaulWist
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AFTER TRIGGER
Продолжу.

Как заставить в триггере работать dynamic-sql или если есть возможность использовать PRIVATE TEMPORARY TABLE без динамики?

На инструкции EXECUTE IMMEDIATE получаю ошибку - ORA-01031: привилегий недостаточно.

Какие права нужны и как их назначить?

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create or replace TRIGGER MyTrigger
FOR INSERT OR UPDATE ON MyTable 
COMPOUND TRIGGER

declare cSql varchar(200);
  
    before statement
    is
    begin

        cSql := 'CREATE PRIVATE TEMPORARY TABLE ora$ptt_my_temp_table (
                  ID       NUMBER,
                  description  VARCHAR2(20)
                )
                ON COMMIT DROP DEFINITION';

        EXECUTE IMMEDIATE cSql;    
   end before statement;
...
END
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / AFTER TRIGGER / 22 сообщений из 22, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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