4

以下のサンプルテーブルのように、他の1つのテーブルを指す複数の外部キーがあり、単一のカスケードが表示されていないテーブルを持つ巨大なレガシーデータベースがあります。

create table Users (
    Id int primary key identity,
    Name varchar(max)
)

create table Products (
    Id int primary key identity,
    Name varchar(max),
    CreatedBy int foreign key references Users(Id),
    UpdatedBy int foreign key references Users(Id)
)

insert into Users values('Bar')
insert into Users values('Baz')
insert into Products values('Foo', 1, 2)

古いデータの一部を削除できるようにする必要がありますが、もちろん参照例外がスローされます。

delete from Users where Name='Bar'

DELETEステートメントがREFERENCE制約「FK__Products__Create__1AD3FDA4」と競合していました。データベース「Foo」、テーブル「dbo.Products」、列「CreatedBy」で競合が発生しました。


データベースが非常に複雑なため、すべての参照を事前に削除することはできません。そのため、カスケードを設定して一時的な外部キーをプログラムで追加しようとしています。ただし、他の1つのテーブルへの複数の外部キーを持つこの特定のテーブルの場合、これcycles or multiple cascade pathsは2番目のUpdatedBy変更になります。

alter table Products add foreign key (CreatedBy) references Users(Id) on delete cascade
alter table Products add foreign key (UpdatedBy) references Users(Id) on delete cascade

テーブル「Products」にFOREIGNKEY制約「FK__Products__Update__1DB06A4F」を導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります。ON DELETENOACTIONまたはONUPDATENO ACTIONを指定するか、他のFOREIGNKEY制約を変更します。


複数のカスケードパスの問題を回避するなどして、参照整合性を維持しながら作業を行うにはどうすればよいdelete from Users whereですか?

4

1 に答える 1

5

個人的には、これは行いません (すべての参照データを事前に削除し、整合性を手動でチェックします)。参照: T-SQL を使用して外部キー制約を一時的に無効にすることはできますか?

見積もり:

-- disable all constraints
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

制約が無効になったらデータを削除しますが、後で再度オンにすることを忘れないでください!

-- enable all constraints
EXEC sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

sp_msforeachtableまた、ストアド プロシージャは文書化されておらず、SQL Server の将来のリリースでは削除される可能性があることに注意してください。

制約を一括で無効にしたくない場合 (おそらく、適用されるテーブルのリストがある場合) は、上記のコードでわかるように、単にそれらを無効にします。

ALTER TABLE [Products] NOCHECK CONSTRAINT ALL
DELETE FROM [Users] where Name='Bar'
ALTER TABLE [Products] WITH CHECK CHECK CONSTRAINT ALL

すべての功績はkristof's answerにあります。投票してください!

于 2012-12-19T11:57:50.760 に答える