Триггер, чтобы избежать удаления последней строки этого значения SQL Server - PullRequest
0 голосов
/ 03 февраля 2019

Так что мне нужно немного помочь, мне нужно создать триггер, который позволяет избежать удаления последней строки значения

Допустим, у меня есть:

SubjectID | ModuleNr  
1792      |   1  
1792      |   2  
1222      |   3

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

Я пробовал разные подходы (с использованием SQL Server 2012), но я не могу использовать ForКаждый после моего FOR DELETE я также не могу выполнить BEFORE DELETE.

Каждый попытанный мной подход все равно позволял мне удалять строку.

Пожалуйста, имейте в виду, что это мой первый семестр в SQLЯ новичок в этом.

Вот моя попытка использовать счетчик, чтобы каким-то образом увидеть, есть ли только 1 значение:

CREATE TRIGGER curriculum.Keep_Last_Module
ON curriculum.Module
FOR DELETE
AS
BEGIN

DECLARE @count AS INT
SET @count = (SELECT COUNT(*) FROM curriculum.Module 
             WHERE SubjectID = (SELECT SubjectID FROM deleted) GROUP BY SubjectID)

    IF (@count = 1)
    BEGIN
    RAISERROR('Last Module Cannot be Erased',16, 1)
    END
END

Заранее спасибо

Ответы [ 4 ]

0 голосов
/ 03 февраля 2019

Кажется, вы хотите, чтобы он автоматически сохранял единицу в случае, если все строки для субъекта будут удалены.

Для этого вам необходим триггер INSTEAD OF, пример ниже (ДЕМО )

CREATE TRIGGER curriculum.Keep_Last_Module
ON curriculum.Module
INSTEAD OF DELETE
AS
  BEGIN
      WITH T
           AS (SELECT *,
                      COUNT(*) OVER (PARTITION BY SubjectID) AS BaseSubjectCount
               FROM   curriculum.Module),
           D
           AS (SELECT *,
                      COUNT(*) OVER ( PARTITION BY SubjectID) AS DeletedSubjectCount,
                      MAX(ModuleNr) OVER (PARTITION BY SubjectID) AS MAXModuleNr
               FROM   deleted)
      DELETE T
      FROM   T
             JOIN D
               ON T.SubjectID = d.SubjectID
                  AND T.ModuleNr = d.ModuleNr
                  AND ( T.BaseSubjectCount <> D.DeletedSubjectCount
                         OR D.ModuleNr <> D.MAXModuleNr );

      IF @@ROWCOUNT < (SELECT COUNT(*) FROM   deleted)
        PRINT 'At least one row was ignored as that would remove the last one for a SubjectID'
  END 
0 голосов
/ 03 февраля 2019

Вы хотите сохранить хотя бы одну строку для каждого предмета.Подсчитайте количество предметов «до» и «после»:

CREATE TRIGGER curriculum.Keep_Last_Module
ON curriculum.Module
INSTEAD OF DELETE
AS
BEGIN
    DECLARE @beforeSubjects INT;
    DECLARE @afterSubjects INT;

    SELECT @beforeSubjects = COUNT(DISTINCT m.subject),
           @afterSubjects = COUNT(DISTINCT CASE WHEN d.ModuleNR IS NULL THEN m.subject END)
    FROM curriculum.Module m LEFT JOIN
         deleted d
         ON m.ModuleNr = d.ModuleNr

    IF (@beforeSubjects <> @afterSubjects)
    BEGIN
        RAISERROR('Last Module Cannot be Erased', 16, 1)
    END;

    DELETE m
        FROM curriculum.module m JOIN
             deleted d
             ON m.ModuleNr = d.ModuleNr;
END;
0 голосов
/ 03 февраля 2019

Вы можете проверить, существует ли строка в deleted, для которой не существует записи в module для того же subjectid, которая имеет большее значение modulenr.

CREATE TRIGGER keep_last_module
               ON module
                  FOR DELETE
AS
BEGIN
  IF EXISTS (SELECT *
                    FROM deleted d
                    WHERE NOT EXISTS (SELECT *
                                             FROM module m
                                             WHERE m.subjectid = d.subjectid
                                                   AND m.modulenr > d.modulenr))
  BEGIN
    THROW 50000, 'The last module cannot be deleted.', 0;
  END;
END;

дб <> скрипка

0 голосов
/ 03 февраля 2019

Я использовал следующий триггер, и он отлично работает в случае удаления одной строки, а в случае удаления нескольких строк это предотвратит всю операцию удаления, если один subjectID нарушит это условие:

CREATE TRIGGER curriculum.Keep_Last_Module
ON curriculum.Module
FOR DELETE
AS
BEGIN

    If exists(SELECT SubjectID FROM deleted except SELECT SubjectID FROM curriculum.module)
      BEGIN
      RAISERROR('Last Module Cannot be Erased',16, 1)
      ROLLBACK
      END
    END
END
...