Триггер на удаление, чтобы избежать висячих ссылок - PullRequest
0 голосов
/ 27 января 2019

У меня проблема с реализацией некоторых триггеров в Oracle.

У меня есть два типа "t_movie" и "t_video", определенные как

CREATE TYPE t_movie AS OBJECT( 
name VARCHAR(20),
year INTEGER);

И

CREATE TYPE t_video AS OBJECT( 
type CHAR,
movie REF t_movie);

И у меня есть также связанные таблицы

CREATE TABLE movies OF t_movie


CREATE TABLE videos OF t_video

Если я удалю кортеж из таблицы фильмов, у меня будут другие кортежи в другой таблице со ссылками на объект, который больше не существует. Как я могу избежать этого? Я думал, что триггер необходим, но я понятия не имею, как его реализовать. Кто-нибудь может мне помочь?

Спасибо.

Edit:

Я попробовал триггер вот так:

CREATE or REPLACE TRIGGER delete_movie_cascade 
  before delete on movies
  for each row
DECLARE
  movie_ref (REF t_movie);
BEGIN
  movie_ref = ref :old;
  dbms_output.put_line(deref(movie_ref).name);
  DELETE FROM videos WHERE movie = movie_ref;
END;

Но, как и ожидалось, я получаю ошибку

Error(6,13): PLS-00103: Encountered the symbol "(" when expecting one of the following:     
constant exception <an identifier>    <a double-quoted delimited-identifier> table long 
double ref    char time timestamp interval date binary national character    nchar

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Документация Oracle Objection Developer говорит о предотвращении висячих ссылок:

Столбец REF может быть ограничен ограничением REFERENTIAL, аналогичным спецификации для внешних ключей.,

К сожалению, документация не дает реального примера того, как это сделать.Форматирование REFERENTIAL предполагает, что это ключевое слово, но оно оказывается красной сельдью.

Решение действительно состоит в том, чтобы определить фактический внешний ключ, но вместо этого использовать ссылки на объекты.Итак, взяв код, который вы разместили, измените определение videos на следующее:

CREATE TYPE t_video AS OBJECT( 
    type CHAR,
    movie REF t_movie
);
/
CREATE TABLE videos OF t_video (
    foreign key (movie) references movies
)
/

Теперь, если вы попытаетесь удалить фильм, на который ссылается видео, Oracle выдаст ORA-02292: integrity constraint.


Триггеры никогда не являются правильным решением для обеспечения ограничений внешнего ключа для обычных или объектных таблиц.Потому что

  1. Запрос таблицы ссылок в триггере FOR EACH ROW неэффективен, особенно для многострочных удалений.Внешние ключи оптимизированы для этой задачи.
  2. Операция небезопасна в многопользовательской среде из-за уровня изоляции зафиксированного чтения.Триггер пройдет наше удаление, когда другой пользователь добавляет дочернюю строку в другой сеанс.
  3. Стандартными являются ограничения внешнего ключа.Отклонение от стандарта - плохая практика, потому что это усложняет поддержку нашего кода.
  4. Правила, применяемые в триггерах, не отображаются в словаре данных.Это запутает наших коллег, предотвратит реверс-инжиниринг модели данных и лишит оптимизатора некоторой полезной информации для выработки эффективных планов выполнения.
0 голосов
/ 27 января 2019

Вместо триггера используйте лучший внешний ключ с каскадным удалением.

Создание ограничения со ссылкой на таблицу t_movie или t_video, как показано ниже:

  ALTER TABLE child_table
  ADD CONSTRAINT fk_delete
  FOREIGN KEY (type)
  REFERENCES t_video (type)
  ON DELETE CASCADE;

С этого момента каждое удаление в t_video вызывает удаление связанных строк в дочерней таблице. И это твоя цель.

Если вам нужно больше деталей, пожалуйста, просмотрите: https://www.techonthenet.com/oracle/foreign_keys/foreign_delete.php

...