Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > МУТАЦИЯ?


Автор: setnull 21.10.2009, 12:42
Все здравствуйте!!!

Как в триггере узнать, замутирована ли та или иная таблица?

Спасибо!!!

Автор: Zloxa 21.10.2009, 13:19
попытаться выбраться и обработать -04091

Автор: azesmcar 21.10.2009, 13:21
Не слышал о таком способе, но для избежания ошибки мутации можно использовать триггеры "AFTER" или использовать http://www.oracle-base.com/articles/misc/AutonomousTransactions.php.

Автор: DimW 26.10.2009, 08:17
Цитата(azesmcar @  21.10.2009,  13:21 Найти цитируемый пост)
но для избежания ошибки мутации можно использовать триггеры "AFTER"

как?
Код

create table TABLE1
(
  ID   NUMBER,
  NAME VARCHAR2(100)
)
/

create or replace trigger trigger_table1
after insert on table1
for each row
declare
  n number;
begin
  select count(*) into n from table1;
end;
/

SQL> insert into table1 values (10, 'xxx')
  2  /
 
insert into table1 values (10, 'xxx')
 
ORA-04091: table TABLE1 is mutating, trigger/function may not see it
ORA-06512: at "TRIGGER_TABLE1", line 4
ORA-04088: error during execution of trigger 'TRIGGER_TABLE1'



Цитата(setnull @  21.10.2009,  12:42 Найти цитируемый пост)
Как в триггере узнать, замутирована ли та или иная таблица?

конечную цель пояснить можете?

Автор: azesmcar 27.10.2009, 16:02
Цитата(DimW @  26.10.2009,  08:17 Найти цитируемый пост)
как?

Интересно, я решал с помощью autonomous transactions. Насчет AFTER тригеров у меня теоретические знания, на сайте было написано, проверю на днях.

Добавлено через 3 минуты и 46 секунд
Цитата

The Oracle mutating trigger error occurs when a trigger references the table that owns the trigger, resulting in the "ORA-04091: table name is mutating, trigger/function may not see it." message.

    * Don't use triggers - The best way to avoid the mutating table error is not to use triggers.  While the object-oriented Oracle provides "methods" that are associated with tables, most savvy PL/SQL developers avoid triggers unless absolutely necessary.
       
    * Use an "after" trigger - If you must use a trigger, it's best to avoid the mutating table error by using an "after" trigger, to avoid the currency issues associated with a mutating table.  For example, using a trigger ":after update on xxx", the original update has completed and the table will not be mutating.
       
    * Re-work the trigger syntax - Dr. Hall has some great notes on mutating table errors, and offers other ways to avoid mutating tables with a combination of row-level and statement-level triggers.
       
    * Use autonomous transactions - You can avoid the mutating table error by marking your trigger as an autonomous transaction, making it independent from the table that calls the procedure.
...

http://www.dba-oracle.com/t_avoiding_mutating_table_error.htm

Автор: DimW 27.10.2009, 16:08
Цитата(azesmcar @  27.10.2009,  16:02 Найти цитируемый пост)
Насчет AFTER тригеров у меня теоретические знания

быть может имелись ввиду стайтмент тригера, а не for each row...

Автор: setnull 27.10.2009, 16:14
Цитата(DimW @ 26.10.2009,  08:17)
конечную цель пояснить можете?

К примеру, есть внешний ключ с каскадным удалением.

В триггерах (delete) дочерней таблицы нужно узнать (либо) обновить некоторою информацию по родительской записи.
При этом если инициирующим действием будет удаление родительской записи - то все...
Можно, конечно и отловить исключение, но вообще можно зарание узнать?

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

Автор: azesmcar 27.10.2009, 16:15
Цитата(DimW @  27.10.2009,  16:08 Найти цитируемый пост)
быть может имелись ввиду стайтмент тригера, а не for each row...

возможно, но в процитированной статье об этом ни слова. Надо проверить и книжку полистать.

Автор: Zloxa 27.10.2009, 16:22
Цитата(setnull @  27.10.2009,  16:14 Найти цитируемый пост)

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

В свое время пытался применить такой подход:
В полцедуре определил default параметры, и если эти параметры не определены, вычитывал их из базы. если процедуру запускаю из триггера, то заполняю параметры.

Добавлено @ 16:24
Цитата(azesmcar @  27.10.2009,  16:15 Найти цитируемый пост)
возможно

azesmcar, я бы на месте DimW использовал бы не выражение "быть может", а "СТО ПУДОВ"

Автор: azesmcar 27.10.2009, 16:27
Цитата(Zloxa @  27.10.2009,  16:22 Найти цитируемый пост)
azesmcar, я бы на месте DimW использовал бы не выражение "быть может", а "СТО ПУДОВ"

намек понял smile 

Автор: DimW 27.10.2009, 16:42
Цитата(setnull @  27.10.2009,  16:14 Найти цитируемый пост)
но вообще можно зарание узнать?

вы имеете ввиду на этапе разработки?
если так по это просто - мутация это появление не консистентных данных, это естетственный процесс который происходит при использовании DML в промежутке между началом выполнения оператора и его завершением, единственное место где на это можно нарваться это строковые тигеры, т.к. один оператор может изменять больше одной позиции в таблице, поэтому при реализации логики в тригерах нужно помнить какие таблицы могут быть задействованы в данной транзакции, любая попытка обратиться к ним приведет к ошибке - которая всего лишь предупреждает вас что данные уже не такие как были до выполнения действия.
если вы это понимаете то есть возможность забить на заботы сервера и воспользоваться  autonomous transactions.
это как вариан, но я так не делаю и вам не советую!
проше реализовать всю вашу логику в процедурах и пользоваться ими для удаления и обновления статистики.

Добавлено через 4 минуты и 41 секунду
Цитата(Zloxa @  27.10.2009,  16:22 Найти цитируемый пост)
использовал бы не выражение "быть может", а "СТО ПУДОВ"

да фиг знает может просто ###статья была  smile 

Автор: Zloxa 27.10.2009, 16:48
Цитата(DimW @  27.10.2009,  16:42 Найти цитируемый пост)
единственное место где на это можно нарваться это строковые тигеры

 smile 
Код

SQL> create table test(val number);
 
Table created
SQL> create or replace function cnt_test return number
  2  is
  3  begin
  4    for i in (select count(*) cnt from test)
  5    loop
  6      return i.cnt;
  7    end loop;
  8  end;
  9  /
 
Function created
SQL> insert into test select cnt_test from dual;
 
insert into test select cnt_test from dual
 
ORA-04091: таблица COMMON.TEST изменяется, триггер/функция может не заметить это
ORA-06512: на  "COMMON.CNT_TEST", line 4

Автор: DimW 27.10.2009, 16:48
решеточки то всетаки поставились  smile

Добавлено через 1 минуту и 55 секунд
Цитата(Zloxa @  27.10.2009,  16:48 Найти цитируемый пост)
insert into test select cnt_test from dual;

ух хитрец!!!! красяво  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)