Почему FOR Trigger не запускается перед действием?

StackOverflow https://stackoverflow.com/questions/801492

  •  03-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь написать триггер для таблицы, чтобы избежать вставки двух имен, которые не помечены как IsDeleted.Но первая часть выборки содержит вставленную, поэтому условие всегда истинно.Я думал, что использование ключевого слова FOR приводит к запуску триггера перед ВСТАВКОЙ, но в этом случае вставленная строка уже находится в таблице.Я ошибаюсь или все триггеры FOR работают именно так?

ALTER TRIGGER TriggerName
ON MyTable
FOR INSERT, UPDATE
AS
BEGIN 
    If exist (select [Name] From MyTable WHERE IsDeleted = 0 AND [Name] in (SELECT [Name] FROM INSERTED)
    BEGIN
    RAISERROR ('ERROR Description', 16, 1);
    Rollback;
    END  
END
Это было полезно?

Решение

FOR запускается после изменения данных, INSTEAD OF - это то, что, я думаю, вам нужно.

РЕДАКТИРОВАТЬ:Как утверждают другие, INSTEAD OF запускается вместо данных, которые вы меняете, поэтому вам необходимо вставить данные, если они действительны, а не останавливать вставку, если они недействительны.

Прочтите этот вопрос для более подробного объяснения типов триггеров.

Триггер SQL Server «AFTER INSERT» не видит только что вставленную строку

Другие советы

FOR — то же самое, что и ПОСЛЕ.если вы хотите «имитировать» триггер BEFORE, используйте INSTEAD OF, будьте осторожны: это не совсем то, что вы ожидаете от правильного триггера BEFORE, т.е.если вы не выполните необходимое действие INSTEAD, ваши вставленные/обновленные данные могут быть потеряны/проигнорированы.

В MSSQL нет триггера BEFORE.

Для SQL Server FOR запускается ПОСЛЕ SQL, который его инициировал.

От:http://msdn.microsoft.com/en-us/library/ms189799.aspx

Для | ПОСЛЕ

ПОСЛЕ Указывает, что триггер DML работает только тогда, когда все операции, указанные в операторе SQL, успешно выполняются.Все ссылочные каскадные действия и проверки ограничений также должны быть успешными, прежде чем этот триггер сжимает.

ПОСЛЕ это по умолчанию, когда для того, чтобы это было единственное указанное ключевое слово.

ПОСЛЕ Триггеры не могут быть определены на взглядах.

Недавно я столкнулся с подобной проблемой и нашел классный способ ее решения.У меня была таблица, которая могла иметь несколько строк для одного идентификатора, но только ОДНА из них могла быть помечена как основная.

В SQL Server 2008 вы сможете создать частичный уникальный индекс примерно так:

create unique index IX on MyTable(name) where isDeleted = 0;

Однако вы можете добиться этого, приложив немного больше усилий в SQL Server 2005.Хитрость заключается в том, чтобы создать представление, показывающее только те строки, которые не были удалены, а затем создать для него уникальный кластерный индекс:

 create view MyTableNotDeleted_vw
 with schema_binding /* Must be schema bound to create an indexed view */
 as
 select name 
 from dbo.MyTable /* Have to use dbo. for schema bound views */
 where isDeleted = 0;

 GO

 create unique clustered index IX on MyTableNotDeleted_vw ( name );

Это фактически создаст уникальное ограничение, влияющее только на строки, которые еще не были удалены, и, вероятно, будет работать лучше, чем пользовательский триггер!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top