2011-01-12 9 views
4

[ONE]、[ONE_TWO]、および[TWO]の3つのテーブルがあるとします。 [ONE_TWO]は、[ONE_ID列と[TWO_ID]列のみを持つ多対多の結合表です。 [ONE]を[ONE_TWO]に、[TWO]を[ONE_TWO]にリンクするように設定された外部キーがあります。 FKはON DELETE CASCADEオプションを使用して、[ONE]または[TWO]レコードが削除された場合、関連する[ONE_TWO]レコードも自動的に削除されます。SQL Server 2005でBEFORE DELETEトリガーをエミュレートする方法

[TWO]レコードが削除されたときに[ONE_ID]をパラメータとして[ONE_ID]値を渡すストアドプロシージャを実行する[TWO]テーブルのトリガが必要です

DECLARE @Statement NVARCHAR(max) 
SET @Statement = '' 
SELECT @Statement = @Statement + N'EXEC [MyProc] ''' + CAST([one_two].[one_id] AS VARCHAR(36)) + '''; ' 
FROM deleted 
JOIN [one_two] ON deleted.[two_id] = [one_two].[two_id] 

EXEC (@Statement) 

は明らかに、私は、BEFOREトリガーをDELETE必要がありますが、私は理由のINSTEAD OFトリガーを使用することはできませんSQL Server 2005の中にはそのような事はありません:[TWO_ID]削除が発生する前にリンクカスケードFK。

FOR DELETEトリガーを使用して[ONE_TWO]に[ONE_ID]値のリストを結合すると、FKカスケードは関連する[ONE_TWO]レコードをすでに削除しているという印象を受けます私は決して[ONE_ID]の値は見つけられません。これは本当ですか?もしそうなら、どうすれば私の目標を達成することができますか?

手動で[TWO]を削除する直前に[TWE]を[ONE_TWO]に変更してカスケードを使用せずに[ONE_TWO]から手動でトリガーで削除する必要があると思っています] 記録。しかし、単純な方法があれば、私はむしろすべてを通過しないだろう。

答えて

8

INSTEAD OFトリガーを使用できます。それは実際の削除の前に(置き換えられ)、従って[one_two]のリンクされたレコードはまだ存在しなければならない。いくつかのサンプルが

insert into one select 1 
insert into one select 2 
insert into one select 3 
insert into two select 11 
insert into two select 12 
insert into two select 13 
insert into one_two select 1,11 
insert into one_two select 1,13 
insert into one_two select 2,13 

今すぐこれは動作しますが、私の状況やあなたが提供されるテストとの違いは、私のテーブルには、制約条件として外部キーを持っているということである

delete two where two_id=13 
+0

それをテスト値

create table [one] (one_id int not null primary key) create table [two] (two_id int not null primary key) create table [one_two] (one_id int, two_id int references two(two_id) on delete cascade) GO CREATE trigger t_del_two on two instead of delete as begin SET NOCOUNT ON DECLARE @Statement NVARCHAR(max) SET @Statement = '' SELECT @Statement = @Statement + N'EXEC [MyProc] ''' + CAST([one_two].[one_id] AS VARCHAR(36)) + '''; ' FROM deleted JOIN [one_two] ON deleted.[two_id] = [one_two].[two_id] PRINT (@Statement) --EXEC (@Statement) -- carry out the actual delete DELETE TWO WHERE two_id in (SELECT two_id from deleted) end GO 

それはすべての違いを作ります。 テーブルを作成する[one_two](one_id int、two_id int); 。 ALTER TABLE [DBO] [one_two] のADD CONSTRAINT [FK_one_two__one_oneid] FOREIGN KEY([one_id]) REFERENCES [DBO] [1]([one_id])DELETE CASCADE ON 。 ALTER TABLE [DBO] [one_two] [FK_one_two__two_twoid] FOREIGN KEY([two_id])制約を追加 REFERENCES [DBO] [2]([two_id]) DELETE CASCADE ON。。。 この変更により、テストが失敗します。 –

+0

Mark、 '' two_id int references two(two_id) ''は、FK参照two(two_id)を作成するためのショートカットです。 one_idとtwo_idのそれぞれを作成したことを除いて、コードとまったく同じです。それを知って、私はあなたのバージョンをとにかくテストし、それはまだ動作します。やってみて。 – RichardTheKiwi

+0

昨日これらの置換文字でスクリプトを実行したところ、547エラーが発生しました。私はちょうどそれをやり直し、それは完全に働いた。私は何かミスタイプする必要があります。助けてくれてありがとう! –

関連する問題