Решение проблемы изменяющейся таблицы в Oracle SQL приводит к тупиковой ситуации.

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

Код запуска:

CREATE OR REPLACE TRIGGER check_thumbnail AFTER INSERT OR UPDATE OF thumbnail ON photograph
FOR EACH ROW
BEGIN
  IF :new.thumbnail = 1 THEN
    check_thumbnail_set_others(:new.url);
  END IF;
END;

Код процедуры:

CREATE OR REPLACE PROCEDURE check_thumbnail_set_others(p_url IN VARCHAR2)
IS PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    UPDATE photograph SET thumbnail = 0 WHERE url <> p_url;
    COMMIT;
END;

Я предполагаю, что вызываю тупик, потому что триггер запускает сам себя. Есть идеи?


person Mat    schedule 27.02.2011    source источник


Ответы (1)


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

Если вы хотите, чтобы данные были согласованными с точки зрения транзакций, вам потребуется несколько триггеров и какой-то способ хранения состояния. Самый простой вариант — создать пакет с коллекцией thumbnail.url%type, а затем создать три триггера для таблицы. Триггер оператора before очистит коллекцию. Триггер уровня строки вставит значение :new.url в коллекцию. Затем триггер оператора after будет считывать значения из коллекции и вызывать процедуру check_thumbnail_set_others (которая не будет автономной транзакцией).

person Justin Cave    schedule 28.02.2011
comment
+1 это стандартный метод решения печально известной проблемы с таблицей мутаций. - person Jeffrey Kemp; 28.02.2011