используя обновление в триггере - PullRequest
0 голосов
/ 17 июня 2019

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

create or replace trigger switch_boss
before delete
on policeman 
for each row
declare
boss number; 
begin
boss := :new.bossid;
if(:new.policemanid = :new.bossid)then
select policemanid into boss from 
(select * from policeman
order by dbms_random.value)
where rownum =1;

end if;

update policeman
set bossid = boss
where bossid = :new.policemanid;

end switch_boss;

Я получил ошибку

ORA-04091: table SYSTEM.POLICEMAN is mutating, trigger/function may not see it
ORA-06512: at "SYSTEM.SWITCH_BOSS", line 13
ORA-04088: error during execution of trigger 'SYSTEM.SWITCH_BOSS'

есть идеи?

UPDATE: Я использовал Compund Trigger его работы, но не так, как я хотел. Я хотел назначить начальника удаленного полицейского начальником для тех, кем он был начальником. проблема в том, что при удалении я не могу определить, какие полицейские имеют удаленного полицейского в качестве босса Я могу найти их, потому что после удаления они имеют нулевое значение в поле, но они могут принадлежать другому удаленному полицейскому.

это триггер, который я нажал:

create or replace trigger switch_boss
  for delete
  on policeman 
compound trigger

  after statement is
  cursor c is select * from policeman where bossid is null for update;
  boss number;

  begin
    for r in c loop

      select policemanid into boss from 
                         (select * from policeman order by dbms_random.value)
                         where rownum =1;

      update policeman
      set bossid = boss
      where current of c;
   end loop;
  end after statement;

end switch_boss;

Ответы [ 2 ]

0 голосов
/ 18 июня 2019

Да, чтобы справиться с этой ситуацией, вам потребуется комбинация триггеров, как указано ниже:

--First of all, You will need one package to hold the values:
CREATE OR REPLACE PACKAGE MY_VALUE_HOLDER AS
    POLICEMANID NUMBER;
    BOSS NUMBER;
END MY_VALUE_HOLDER;
/

-- Before each row trigger
CREATE OR REPLACE TRIGGER SWITCH_BOSS_ROW_TRG BEFORE
    DELETE ON POLICEMAN
    FOR EACH ROW
DECLARE
    BOSS   NUMBER;
BEGIN
    BOSS := :OLD.BOSSID;
    IF ( :OLD.POLICEMANID = :OLD.BOSSID ) THEN
        SELECT
            POLICEMANID
        INTO BOSS
        FROM
            (
                SELECT
                    *
                FROM
                    POLICEMAN
                ORDER BY
                    DBMS_RANDOM.VALUE
            )
        WHERE
            ROWNUM = 1;

    END IF;

    MY_VALUE_HOLDER.POLICEMANID := :OLD.POLICEMANID;
    MY_VALUE_HOLDER.BOSS := BOSS;
END SWITCH_BOSS_ROW_TRG;
/


--After statement trigger
CREATE OR REPLACE TRIGGER SWITCH_BOSS_ST_TRG AFTER
    DELETE ON POLICEMAN
BEGIN
    UPDATE POLICEMAN
    SET
        BOSSID = MY_VALUE_HOLDER.BOSS
    WHERE
        BOSSID = MY_VALUE_HOLDER.POLICEMANID;

END SWITCH_BOSS_ST_TRG;
/

Первый триггер перед каждой строкой, а второй после триггера оператора.

Демонстрация DB Fiddle

Ура !!

0 голосов
/ 17 июня 2019

Это очень распространенная проблема при начале работы с триггерами. Oracle не позволяет вашему уровню строки триггеру обращаться к своей базовой таблице (POLICEMAN), кроме как через псевдозаписи :NEW и :OLD. Идея состоит в том, что таблица находится в состоянии изменения, поэтому она не может быть запрошена или изменена триггером.

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

Вот описание того, как это сделать: Избавьтесь от ошибок триггера мутирующей таблицы с помощью составного триггера

В этой статье Стивен Фюрштайн описывает не только традиционное решение проблемы на основе пакетов, но и более современное решение на основе составных триггеров.

...