ORA-04091: таблица JOSEP.EMP мутирует, триггер / функция может ее не видеть - PullRequest
0 голосов
/ 11 апреля 2019

"ORA-04091: таблица JOSEP.EMP мутирует, триггер / функция может ее не видеть"

Мне нужно показать сообщение со старой и новой зарплатой, икод занятого (emp_no) в нем, и я не могу это сделать.

create or replace trigger emp_AU 
after update of salario 
on emp for each row
    declare
    v_emp_no emp.emp_no%type;  
    begin
    select emp_no into v_emp_no FROM emp;
    insert into auditaemple VALUES ((select count(*) from auditaemple)+1, 'El salario del empleado '||v_emp_no||'antes era de '||:old.salario||' y ahora será '||:new.salario, sysdate);
    end emp_AU;

Выполнение этого приводит к ошибке «ORA-04091:».Если я исключу v_emp_no, я не получу сообщение, но мне нужно показать код занятого.Что я не так делаю.

Заранее благодарен.

1 Ответ

1 голос
/ 11 апреля 2019

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

Нет необходимости выбирать emp_no; он у вас уже есть - укажите псевдокорд :new. Кроме того, как вы это сформулируете, вы получите ошибку TOO-MANY-ROWS, поскольку нет условия WHERE, которое ограничивало бы набор результатов одной строкой.

Не используйте count + 1 (ни max + 1 или подобную «технику»), особенно если вы собираетесь заполнить столбец, который должен быть уникальным. Пока он будет работать в однопользовательской среде, он не сможет (рано или поздно) в многопользовательской. Используйте последовательность (или, если ваша база данных это поддерживает, столбец идентификаторов).

Вот рабочий пример того, как вы могли это сделать.

Во-первых, контрольный пример:

SQL> create table temp as select empno emp_no, sal salario
  2                       from emp where deptno = 10;

Table created.

SQL> create table auditaemple (id number, text varchar2(100), datum date);

Table created.

SQL> create sequence seqa;

Sequence created.

Trigger:

SQL> create or replace trigger trg_bu_emp
  2    before update of salario on temp
  3    for each row
  4  begin
  5    insert into auditaemple (id, text, datum)
  6      values (seqa.nextval,
  7              'El salario del empleado '||:new.emp_no||' antes era de '||
  8               :old.salario||' y ahora será '||:new.salario, sysdate);
  9  end;
 10  /

Trigger created.

Тестирование:

SQL> select * from temp;

    EMP_NO    SALARIO
---------- ----------
      7782       2450
      7839       5000
      7934       1300

SQL> update temp set salario = 9000 where emp_no = 7839;

1 row updated.

SQL> select * From auditaemple;

        ID TEXT                                     DATUM
---------- ---------------------------------------- ----------------
         1 El salario del empleado 7839 antes era d 11.04.2019 21:47
           e 5000 y ahora será 9000


SQL>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...