我正在尝试在表上写一个触发器,以避免插入两个未标记为IsDeleted的Name。但是选择的第一部分包含插入的部分,因此条件始终为真。我虽然使用FOR关键字导致触发器在INSERTION之前运行,但在这种情况下插入的行已经在表中。我错了还是所有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与AFTER相同。如果你想“模拟”在触发之前,使用INSTEAD OF,请注意,这并不是您在正确的BEFORE触发器上所期望的,即如果您未能提供必要的INSTEAD操作,则插入/更新的数据可能会丢失/忽略。

MSSQL没有BEFORE触发器。

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

自: http://msdn.microsoft.com/en-us/library/ms189799。 ASPX

  

FOR | AFTER

     

AFTER 指定DML触发器   只有在所有操作时才会被触发   在触发SQL中指定   声明已成功执行。   所有参考级联行动和   约束检查也必须成功   在此触发器触发之前。

     当FOR为时,

AFTER 是默认值   仅指定关键字。

     

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

我最近遇到了类似的问题,并找到了一种很酷的方法来处理它。我有一个表可以为一个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 );

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top