2009-04-29 35 views
2

我想在表上写一个触发器,以避免插入两个未标记为IsDeleted的名称。但选择的第一部分包含插入的部分,因此条件始终为真。我虽然使用FOR关键字会导致触发器在INSERTION之前运行,但在这种情况下插入的行已经在表中。我错了还是这是所有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 

回答

2

FOR在数据更改后运行,INSTEAD OF是我认为你在做的事。

编辑:正如别人所说,INSTEAD OF运行而不是你正在改变的数据,因此你需要插入数据,如果它是有效的,而不是停止插入,如果它是无效的。

请阅读此问题以获取关于触发器类型的更详细说明。

SQL Server "AFTER INSERT" trigger doesn't see the just-inserted row

+0

而是表示触发器将执行而不是执行的命令 – 2009-04-29 08:59:08

1

FOR是一样的了。如果您想“模拟”BEFORE触发器,请使用INSTEAD OF,注意,这与BEFORE触发器的期望不符,即如果您未能提供必要的INSTEAD操作,则可能会丢失/忽略插入/更新的数据。

MSSQL没有BEFORE触发器。

0

对于SQL Server,FOR会在触发它的SQL之后运行。

来源: http://msdn.microsoft.com/en-us/library/ms189799.aspx

FOR | AFTER

规定,只有在触发SQL 语句中指定的所有操作 已成功执行DML触发器 被触发。 所有引用级联操作和 约束检查也必须在触发器触发前成功执行 。

AFTER是默认的,当FOR是 唯一指定的关键字时。

AFTER触发器 无法在视图上定义。

0

我最近遇到了类似的问题,并找到了一个很酷的方式来处理它。我有一张桌子,可以有一个ID为几行,但只有其中一个可以标记为主。

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

这将有效地创建仅影响那些尚未行的唯一约束删除,并可能会执行比自定义触发器更好!