Триггер INSTEAD OF DELETE для предотвращения удаления, если условие выполнено - PullRequest
1 голос
/ 14 апреля 2019

Я пытаюсь настроить триггер INSTEAD OF DELETE для таблицы с именем Cast в моей базе данных Movies. Я хочу, чтобы предотвратить удаление строки, если счетчик CastFilmID больше 2

CREATE TRIGGER Prevent_Cast_Delete ON Cast
INSTEAD OF DELETE 
AS
WHERE COUNT CastFilmID > 2
RAISERROR ('Contains more than 2 cast memebers',16,1)
ROLLBACK TRAN
RETURN;

1 Ответ

1 голос
/ 14 апреля 2019
CREATE TRIGGER Prevent_Cast_Delete ON Cast
INSTEAD OF DELETE 
AS 
BEGIN
  DELETE FROM Cast WHERE id IN (
    --Identify only people who work in films with 0 or 1 cast members
    SELECT d.id 
    FROM
      --The list of people we try to delete (request from elsewhere)
      Deleted d 
      LEFT OUTER JOIN 
      --This query counts the cast for every film 
      (SELECT CastFilmID, COUNT(*) as CastCount FROM Cast GROUP BY CastFilmId) c 
      ON
        c.CastFilmID = d.CastFilmID
    --This where clause reduces the list of actor IDs we try to delete, to actually
    --just those actors who are in a film of 1 cast member
    WHERE c.CountCast < 2 OR d.CastFilmID IS NULL
  );
END;

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

Я перевернул логику: для всех записей, которые вы пытаетесь удалить,

могут быть удалены только записи, относящиеся к актеру, который делит фильм с другим актером. * Для этого мы берем список людей, которые приложение (например) пыталось удалить, - deleted d псевдотаблица, присоединяйтесь к немув сводку таблицы актеров и выбирайте только записи, в которых эта сумма насчитывает <2 актеров: </p>

Cast.ID, Cast.CastFilmID
KEANU, MATRIX
LAURE, MATRIX
HUGOW, MATRIX
JARAN, MOBYDI
JESUS, null

Предположим, я говорю delete from cast where id in ('KEANU','JARAN','JESUS') - это пытается удалить людей из каждого фильма, который мы знаем.Он реализует псевдотаблица deleted из:

Cast.ID, Cast.CastFilmID
KEANU, MATRIX
JARAN, MOBYDI
JESUS, null

. Слева на этот счет добавлено количество фильмов:

Cast.ID, Cast.CastFilmID, CastCount
KEANU, MATRIX, 3
JARAN, MOBYDI, 1
JESUS, null, null

Предложение WHERE удаляет KEANU из результатов, потому что он работает надфильм 3 актеров (включая его самого)

Следующие 2 записи запрошенных оригиналов 3 удалены (DELETE FROM cast WHERE ID IN (...this list...):

Cast.ID
JARAN
JESUS

Обратите внимание, что следующие предположения о вашей БД имеютбыло сделано:

  • В таблице Cast есть столбец идентификаторов, уникальный для каждого актерского фильма
  • CastFilmId - это идентификатор из таблицы фильмов, и он повторяется для всех, кто работает надтот же фильм
  • Когда актер для фильма не снимается в этом фильме (возможно ли это?), я предположил, что его CastFilmID равен нулю. Если это никогда не будет равно нулю, можно было бы внести некоторые упрощения в запрос, но в этой форме я предполагал, что записи, в которых актер не назначен для фильма, все еще могут быть удалены

Здесь важно понять, что кто-то, выполняющий запрос на удаление, будетдать вам X количество строк в вашем триггере;это те строки, которые человек пытается удалить, но вам нужно дополнительные знания извне этого набора данных (например, «сколько других людей работают над теми же фильмами, что и каждый из этих людей»), прежде чем вы сможетерешить, удалять их или нет.Вот почему мы подсчитываем количество людей в этом фильме, присоединяем его к данным удаляемого человека и ТОГДА решаем, следует ли удалить этого человека

Действительно, этот вид магии должен быть сделан впередний конец.Все становится очень запутанным, когда вы говорите БД удалить что-то, а это не так.Точно так же вам следует помнить, что запросы DELETE могут удалять сотни строк за раз, поэтому вы не можете использовать упрощенный подход «удаление будет когда-либо пытаться удалить только одну строку преобразования» - вы должны работать над этими вещами, какнаборы данных, объедините их с другими наборами данных и получите набор данных, который необходимо удалить

...