Почему FOR Trigger не работает перед действием? - PullRequest
2 голосов
/ 29 апреля 2009

Я пытаюсь написать триггер в таблицу, чтобы избежать вставки двух имен, которые не помечены как IsDeleted. Но первая часть выделения содержит вставленную, поэтому условие всегда выполняется. Я думал, что использование ключевого слова 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

Ответы [ 4 ]

2 голосов
/ 29 апреля 2009

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

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

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

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

1 голос
/ 29 апреля 2009

FOR совпадает с AFTER. если вы хотите «смоделировать» ПЕРЕД триггером, используйте INSTEAD OF, будьте осторожны, это не совсем то, что вы ожидаете от правильного ПЕРЕД триггером, т. е. если вы не предоставите необходимое действие INSTEAD, вставленные / обновленные данные могут быть потеряны / проигнорированы.

MSSQL не имеет ПЕРЕД триггером.

0 голосов
/ 01 мая 2009

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

В 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 );

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

0 голосов
/ 29 апреля 2009

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

Из: http://msdn.microsoft.com/en-us/library/ms189799.aspx

FOR | ПОСЛЕ

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

ПОСЛЕ - значение по умолчанию, если FOR указано только ключевое слово.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...