powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Oracle [игнор отключен] [закрыт для гостей] / AFTER TRIGGER
22 сообщений из 22, страница 1 из 1
AFTER TRIGGER
    #40127725
PaulWist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Братья!

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

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

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

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

Не будем гадать.
Пусть ТС объяснит свою проблему "нормально, на гражданском языке" (с) Джентльмены удачи
...
Рейтинг: 0 / 0
AFTER TRIGGER
    #40127739
PaulWist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
AFTER TRIGGER
    #40127745
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PaulWist

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


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

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

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


Ммм, вы предлагаете создать в триггере уникальный индекс? неожиданно
...
Рейтинг: 0 / 0
AFTER TRIGGER
    #40127760
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
AFTER TRIGGER
    #40127767
PaulWist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
AFTER TRIGGER
    #40127775
Алымов Анатолий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Создайте compound trigger. В after for each rows заполняешь коллекцию уникальную. В after statement обрабатываешь коллекцию.
...
Рейтинг: 0 / 0
AFTER TRIGGER
    #40127783
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PaulWist

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


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

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


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

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


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

SY.
...
Рейтинг: 0 / 0
AFTER TRIGGER
    #40127800
ANB-ANB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: 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
AFTER TRIGGER
    #40127821
PaulWist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ANB-ANB,

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

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

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

.....
stax


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

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

.....
stax


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


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

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

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

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


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

Как заставить в триггере работать 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
22 сообщений из 22, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / AFTER TRIGGER
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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