2009-04-29 6 views
2

IsDeletedとしてフラグが立てられていない2つの名前の挿入を避けるために、テーブルにトリガーを書き込もうとしています。しかし、選択の最初の部分には挿入された部分が含まれているため、条件は常に真です。私はFORキーワードを使用するとINSERTより前にトリガが実行されますが、この場合、挿入された行はすでにテーブルにあります。私は間違っていますか、これはどのようにトリガーが働くかです。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はあなたが後になったと思います。

EDIT:変更中のデータの代わりにINSTEAD OFが実行されるため、無効な場合に挿入を停止するのではなく、有効な場合はデータを挿入する必要があります。

トリガーの種類の詳細については、この質問をお読みください。 FOR

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

+0

代わりに、実行しているコマンドの代わりにトリガーが実行されることを意味します –

1

はAFTERと同じです。 BEFOREトリガーをシミュレートする場合は、INSTEAD OFを使用してください。正しいBEFOREトリガーで期待通りのものではありません。つまり、必要なINSTEADアクションを提供できない場合、挿入/更新されたデータは失われたり無視されたりする可能性があります。

MSSQLにはBEFOREトリガがありません。

0

SQL Serverの場合、FORはトリガされたSQLの後に実行されます。

から:FOR http://msdn.microsoft.com/en-us/library/ms189799.aspx

| AFTER

は、トリガーSQL 文で指定されたすべての操作 が正常に実行された場合にのみ、DMLトリガー が発射されるように指定しました。 すべての参照カスケードアクションおよび 制約チェックも、このトリガが起動する前に、 を成功させる必要があります。

FORが キーワードのみ指定されている場合は、がデフォルトになります。

アフタートリガー ビューで定義することはできません。

0

私は実際に最近同様の問題に遭遇し、それを処理するクールな方法を見つけました。 1つのIDに対して複数の行を持つテーブルがありましたが、そのうちの1つだけがプライマリとしてマークされていました。

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

は、しかし、あなたはSQL Server 2005でもう少し作業とそれを達成することができます:

SQL Server 2008では、あなたは、このような部分的な一意のインデックス何かを作ることができるでしょう。トリックは削除されていない行のみを示す図を作成し、それに独自のクラスタ化インデックスを作成することです:

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

これが効果的にだけではまだされていない行に影響を与えるユニーク制約を作成します。削除され、おそらくカスタムトリガーよりも優れたパフォーマンスを発揮します!